How to add up int pointer values in a linked list in C++? - c++

I've been working at this homework assignment for awhile and I can't figure out what I'm doing wrong. How my program is suppose to work:
User enters as many positive numbers as they so desire,
Numbers are in a linked list,
Numbers entered should be added up,
Divide by the amount of numbers entered,
Resulting in the average,
However, it's not working out as I had intended and I've been playing with this for over 3 hours now. I'd contact my teacher but she hasn't responded to my last message still and I need assistance right away. Thanks in advance.
Note: I need to traverse the list to add up all the entered numbers and count the number of nodes.
#include <iostream>
using namespace std;
int num, total, num_entries = 1;
struct number_node
{
int number;
number_node *next;
};
number_node *head_ptr;
number_node *current_ptr;
int get_number_data(int &number);
void add_node(int &number);
void move_current_to_end();
void display_avg();
void delete_list();
int main()
{
if(get_number_data(num))
{
head_ptr = new number_node;
head_ptr->number = num;
head_ptr->next = NULL;
while(get_number_data(num))
{
add_node(num);
}
display_avg();
delete_list();
}
system("pause");
return 0;
}
int get_number_data(int &number)
{
int keep_data = 1;
cout << "Enter a positive number (Enter a negative number to stop): ";
cin >> num;
if(num < 0)
{
keep_data = 0;
}
return(keep_data);
}
void add_node(int &number)
{
number_node *new_rec_ptr;
new_rec_ptr = new number_node;
new_rec_ptr->number = num;
new_rec_ptr->next = NULL;
move_current_to_end();
current_ptr->next = new_rec_ptr;
}
void move_current_to_end()
{
current_ptr = head_ptr;
num_entries++;
while(current_ptr->next != NULL)
{
current_ptr = current_ptr->next;
total = current_ptr->number + total;
}
}
void display_avg()
{
current_ptr = head_ptr;
cout << "Average = " << total / num_entries << endl;
}
void delete_list()
{
number_node *temp_ptr;
current_ptr = head_ptr;
do
{
temp_ptr = current_ptr->next;
delete current_ptr;
current_ptr = temp_ptr;
}
while(temp_ptr != NULL);
}

Right now you're mixing your data structure (linked list) with what you intend to use it for. Consider splitting your logic into:
Your I/O code.
The linked list implementation.
A function that takes a linked list, and computes the average.

You've got a lot of other stuff there and you didn't say what your code does, but I'd do something like this (untested):
int count = 0;
int total = 0;
for (ptr = head_ptr; ptr != NULL; ptr = ptr->next)
{
total += ptr->number;
count++;
}

I know this won't help you with your homework, but here is a C++ STL program that satisfies your requirements:
As many inputs as the user desires
Numbers are stored in a linked list
Numbers are added up
Calculates and displays average
Good luck with your class.
#include <list>
#include <iterator>
#include <iostream>
#include <algorithm>
#include <numeric>
int main()
{
std::list<double> l;
std::copy(std::istream_iterator<double>(std::cin),
std::istream_iterator<double>(),
std::insert_iterator<std::list<double> >(l, l.begin()));
size_t size = l.size();
if(size)
std::cout << std::accumulate(l.begin(), l.end(), 0.0) / l.size()
<< std::endl;
}
~

Apologies: would have attached a comment to ask this introductory question. But apparently you need a higher rep than i currently have to do so.
#Brandon. Can i get you to clearly state that it is these functions:
int get_number_data(int &number)
void add_node(int &number)
void move_current_to_end()
void display_avg()
and only these that you are allowed to use? (And i quote you: "I just have to have it figure out the total and and # of nodes using those functions"
If so. Why? Have they been specified by your lecturer?

Related

Returning name of lowest node

First of all, this is part of a university course, so whilst a copy-paste solution would do, I'm looking for a bit more depth. I'll be seeing my supervisor tomorrow anyways though.
Now onto the problem. I am implementing Dijkstra's algorithm for 5 linked nodes, A-E, which have their associated costs and links stored in a vector;
struct Node
{
char nodeLink; //adjacent link
int cost; //cost of a link
}; //to use in Dijkstra algorithm
class HeadNode
{
public:
char Name;
bool Visited;
vector<Node> nodes;
HeadNode(char x) { Name = x; Visited = false; }
};
class Graph
{
char Start = 'A';
char StartNode;
char CurrentNode;
char Destination = 'E';
int TotalCost = 0;
vector<HeadNode> hnode;
vector<char> path;
vector<int> weight;
public:
Graph();
void createHeadNode(char X);
void createAdjMatrix();
char LeastDistance(char node);
void printAdjMatrix();
void Dijkstra(char StartNode);
char GetStartNode();
};
int main()
{
Graph graph;
graph.createHeadNode('A');
graph.createHeadNode('B');
graph.createHeadNode('C');
graph.createHeadNode('D');
graph.createHeadNode('E');
graph.createAdjMatrix();
//graph.printAdjMatrix();
graph.Dijkstra(graph.GetStartNode());
system("pause");
return 0;
}
Graph::Graph()
{
}
void Graph::createHeadNode(char x)
{
hnode.push_back(x);
}
In order to properly implement the algorithm, I have created a precursor function, LeastDistance(), within the class graph. I also have a function to get the start node, but that isn't particularly important here;
char Graph::LeastDistance(char node)
{
int smallest = 9999;
char smallestNode;
for (int i = 0; i < hnode.size(); i++)
{
for (int j = 0; j < hnode[i].nodes.size(); ++j)
{
if ((node == hnode[i].Name) && (hnode[i].nodes[j].cost <= smallest) && (hnode[i].Visited == false))
{
smallest = hnode[i].nodes[j].cost;
smallestNode = hnode[i].nodes[j].nodeLink;
}
else
{
hnode[i].Visited = true;
break;
}
}
}
TotalCost = TotalCost + smallest;
return(smallestNode);
}
void Graph::Dijkstra(char StartNode)
{
CurrentNode = StartNode;
if (CurrentNode == Destination)
{
cout << "the start is the destination, therefore the cost will be 0." << endl;
}
else
{
while(true)
{
if (CurrentNode != Destination)
{
CurrentNode = LeastDistance(StartNode);
cout << CurrentNode << "<-";
}
else if (CurrentNode == Destination)
{
cout << endl;
cout << "The total cost of this path is:" << TotalCost;
TotalCost = 0;//reset cost
break;
}
}
}
}
My problem is that the LeastDistance fucntion appears always to return node C, leading to it being printed over and over, so it fills the console. So far, I have tried to debug using visual studio 2017, but I cant make much sense out of the watches. I have also tweaked the order of the breaks around, and tried to make sure the visited flag is being set to true. whether any precedence of operations is affecting this I am not sure.
Thanks in advance.
I would contend that there are multiple problems with the way you implement this... but I think the one that's causing you the problem you describe is the statement right here:
if (CurrentNode != Destination)
{
CurrentNode = LeastDistance(StartNode);
cout << CurrentNode << "<-";
}
Think about what this does. Let's say your first node isn't the one you're looking for, then you call least distance and find the next smallest node. Then you print it. Then you iterate on the while loop again only to find that CurrentNode isn't the one you're looking for, so you call LeastDistance(StartNode) again, which will return the exactly same value. Thus, you'll keep printing the same result which apparently is c.
Assuming everything else is correct, I think you want:
CurrentNode = LeastDistance(CurrentNode);

Pouring via Depth First Search node linking to itself. C++

Working on a program to solve the pouring problem:
I believe I am down to one last issue. My data structure is as follows:
I have an vector of Node pointers and each node contains a int array, and an address to the next node. In testing everything functions properly. The goal of this data structure is to basically function as an adjacency list. Where each node is linked to the nodes that it would have an edge to.
Currently my problem is when I am attempting to link these nodes to one another:
the LinkState function that I have should accomplish this, however it is instead resulting in the program running...forever.
The function should simply iterate through the individual nodes linked list and find where to connect the new node. Instead it is causing a node to constantly be leak to itself..which is leading to the runtime issue.
Sorry if this is a bit confusing. Any help would be greatly appreciated.
p.s. I know there are better ways to solve this problem like BFS, I'd like to stick to DFS.
#ifndef _POURINGLIST_H_
#define _POURINGLIST_H_
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
struct Node{
int state[3];
Node* next = NULL;
};
class PouringList{
Node* init;
vector<Node*> Head;
int max[3];
int steps;
public:
PouringList(){
//max values for comaprison
max[0] = 10;
max[1] = 7;
max[2] = 4;
//init values to begin DFS
init = new Node;
init->state[0] = 0;
init->state[1] = 7;
init->state[2] = 4;
};
//private methods not to be called by user
private:
//pours some good old h2o
Node pour(Node* curr_state, int A, int B){
int a = curr_state->state[A];
int b = curr_state->state[B];
int change = min(a, max[B]-b);
Node newState = *curr_state;
newState.state[A] = (a-=change);
newState.state[B] = (b+=change);
return newState;
}
//O(n) complexity used to check if a node is already in head
bool isIn(Node* find_me){
for(vector<Node*>::iterator i = Head.begin(); i != Head.end(); i++) {
if (equal(begin(find_me->state), end(find_me->state), begin((*i)->state)))
return true;
}
return false;
}
void printNode(Node* print){
for(int i = 0; i < 3; i++){
cout << print->state[i] << " ";
}
cout << endl;
}
int locate(Node* find_me){
for(vector<Node*>::iterator i = Head.begin(); i != Head.end(); i++) {
if (equal(begin(find_me->state), end(find_me->state), begin((*i)->state)))
return distance(Head.begin(), i);
}
return -1;
}
void LinkState(Node* head, Node * nxt){
Node* vert = Head[locate(head)];
while(vert->next != NULL){
vert = vert->next;
}
vert->next = nxt;
}
public:
void DFS(){
steps = 0;
//start exploring at initial value
explore(init);
}
void explore(Node* vertex){
//base case to end
if(!isIn(vertex)){
Head.push_back(vertex);
if(vertex->state[1] == 2 || vertex->state[2] == 2){
cout << steps << endl;
printNode(vertex);
return;
}
//generate all possible states and connects them to Head vertex
else{
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
Node conn1 = pour(vertex,i,j);
Node *conn = &conn1;
if(i!=j && !isIn(conn)){
cout << i << " adds water to " << j << endl;
LinkState(vertex, conn);
}
}
}
}
Node* Nextex = vertex;
//printNode(vertex);
while(Nextex != NULL){
//new neighbor
if(!isIn(Nextex)){
//printNode(Nextex);
explore(Nextex);
}
Nextex = Nextex->next;
}
}
//printNode(Nextex);
else{
cout <<"Dead end" << endl;
}
}
//start from init node and show path to solution
void display(){
Node *output;
for(int i = 0; i < Head.size(); i++){
output = Head[i];
while ( output != NULL){
printNode(output);
output = output->next;
}
cout << '#' <<endl;
}
}
};
#endif // _POURINGLIST_
basic driver:
#include "PouringList.h"
int main(){
PouringList s1;
s1.DFS();
}
Edit
I've attempted the suggested fix before (This is what I'm assuming you mean). It still lead to the programming running forever. Also I do not know enough about smartpointers to go and overhaul the application!
Node conn1 = pour(vertex,i,
Node *conn = new Node;
conn = &conn1;
You are storing the address of a local variable in your list.
In explore, you have
Node conn1 = pour(vertex,i,j);
Node *conn = &conn1;
then later pass conn to LinkState, which stores that pointer in your PouringList. All your added nodes will point at the same memory address.
What you should be doing is allocating a new Node and using that (preferably using some sort of smart pointer rather than storing raw pointers so the clean up will happen automatically).

Counting number of occurrences of a string in a Hash Table

I am writing my own HashTable class in C++ and need to output to the user the number of occurrences of each string in the table. For example, if this is the input: testing, 1, 2, testing, and this is the hash table (done with chaining, and node pointers):
[0]->testing, testing
[1]->2
[2]->1
this would be the output to the user (the count, followed by the word):
2 testing
1 2
1 1
The problem I'm having is how to keep track of how many of each word is in the Hash Table, or how to find it. I started with this question but was unable to implement another array in my code.
I also tried the solution in this question, but it didn't work because of my use of pointers/chained hashing.
My question is, do I need to use a separate array of strings to keep track of what's already been used, or is there an easy way to recursively go through each index of the Hash Table and print out the number of occurrences of each string? I think I need to accomplish this in either my insert function or my printData function.
For reference, here is my code:
HashTable.h:
#include <string>
#include <iostream>
using namespace std;
struct Entry {
string word;
Entry* next;
};
class HashTable {
public:
HashTable();
HashTable(int);
int hash(string);
void insert(string);
void printData();
int getCapacity() const;
private:
//Member variables
int CAPACITY; // The initial capacity of the HashTable
Entry **data; // The array to store the data of strings (Entries)
};
HashTable.cpp:
#include "HashTable.h"
HashTable::HashTable()
{
CAPACITY = 0;
data = new Entry*[0];
}
HashTable::HashTable(int _cap)
{
CAPACITY = _cap;
data = new Entry*[_cap];
for (int i = 0; i < CAPACITY; i++) {
data[i] = new Entry;
data[i]->word = "empty";
data[i]->next = nullptr;
}
}
int HashTable::hash(string key)
{
int hash = 0;
for (unsigned int i = 0; i < key.length(); i++) {
hash = hash + (int)key[i];
}
return hash % CAPACITY;
}
void HashTable::insert(string entry)
{
int index = hash(entry);
if (data[index]->word == "empty") {
data[index]->word = entry;
} else {
Entry* temp = data[index];
Entry* e = new Entry;
e->word = entry;
e->next = nullptr;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = e;
}
}
void HashTable::printData()
{
for (int i = 0; i < CAPACITY; i++) {
if (data[i]->next != nullptr) {
while(data[i]->next != nullptr) {
cout << data[i]->word << " -> ";
data[i] = data[i]->next;
}
cout << data[i]->word << endl;
} else {
cout << data[i]->word << endl;
}
}
}
int HashTable::getCapacity() const
{
return CAPACITY;
}
NOTE: I can't use any function/data structure from the standard C++ Library.
I only see two options here
Traverse entire linked list to count occurances. Use a map< string, int > to count occurances for each string.
You should make your linked list sorted. So when you insert a new node, you will insert it in its exact place. You can use strcmp for comparison. This way you can count every word exactly in one traverse and using just one integer variable, but your insert time and complexity will increase.

Accessibility for Vectors of Singly Linked Lists (or possibly a Linked List of Linked Lists)

Been wracking my mind all day trying to hammer out the underlying data structures for a challenge assignment in one of my programming classes.
The problem is as follows:
Given an assortment of objects (each of which includes an identifier and a weight) and a supply of containers (which have a fixed weight capacity), pack all the items using as few containers as possible without overloading any of them.
I have the logic aspects hammered out using a hodgepodge of arrays, but the dynamic nature of this assignment has me wanting to optimize things by using vectors and/or linked lists.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <math.h>
#include <time.h>
#include <conio.h>
#include <vector>
#include <algorithm>
using namespace std;
struct Item
{
int number;
double weight;
bool operator < (const Item& str) const
{
return (weight < str.weight);
}
};
class Node
{
int number;
double weight;
Node* next;
public:
Node()
{};
void SetID(int iNum)
{
number = iNum;
};
void SetWeight(double iWeight)
{
weight = iWeight;
};
void SetNext(Node* iNext)
{
next = iNext;
}
int GetID()
{
return number;
};
double GetWeight()
{
return weight;
};
Node* Next()
{
return next;
};
};
class List
{
Node* head;
double weight;
public:
List()
{
head = NULL;
weight = 0;
};
int Size()
{
Node* tmp;
int count = 0;
for (tmp = head; tmp != NULL; tmp = tmp->Next())
{
count++;
}
return count;
};
double Weight()
{
return weight;
};
void Print()
{
Node *tmp = head;
if ( tmp == NULL )
{
cout << " E M P T Y" << endl;
return;
}
do
{
cout << setw(8) << tmp->GetID() << " | " << setw(8) << tmp->GetWeight() << endl;
tmp = tmp->Next();
} while ( tmp != NULL );
};
void Append(int iNum, double iWeight)
{
Node* newNode = new Node();
newNode->SetID(iNum);
newNode->SetWeight(iWeight);
newNode->SetNext(NULL);
Node *tmp = head;
if ( tmp != NULL )
{
while ( tmp->Next() != NULL )
{
tmp = tmp->Next();
}
tmp->SetNext(newNode);
}
else
{
head = newNode;
}
weight += iWeight;
};
};
double ItemWeights(vector<Item> iVect)
{
double total = 0;
for(int i = 0; i < iVect.size(); i++)
{
total += iVect[i].weight;
}
return total;
}
int main()
{
const double MAX_WEIGHT = 20;
vector< Item > source;
//
// Segment of code which propagates the vector data
// works fine, but is excluded for the sake of brevity
//
double totalWeight = ItemWeights(source);
// Duplicate vector of items
vector< Item > items(source);
for(int i = 0; i < items.size(); i++)
{
cout << setw(8) << items[i].number << setw(8) << items[i].weight << endl;
}
cout << "\n Total weight = " << totalWeight << endl;
cout << "\n\n Press any key to continue... ";
getch();
// Solution A-Original
// vector< vector< Item > > boxesAO( vector< Item >);
// boxesAO[0].push_back({items[items.size()].number, items[items.size()].weight});
vector< List > boxesAO;
// boxesAO[0].Append(items[items.size()].number, items[items.size()].weight);
return 0;
}
I've left some of the methods I've tried in the code (commented out) - none of which worked. As I mentioned above, I've got it working with arrays of linked lists and with 2D arrays, but the vast range of potential input makes these problematic at best. Either a bunch of empty lists taking up space or, worse, not having enough.
I'm thinking that vector< List > is my best option, but I can't figure out how I'm supposed to access any of the List functionality.
If someone would be so helpful as to offer a suggestion for how to create a "dynamic 2D array" as well as a code example of how to access it, I would be most greatly appreciative. My deepest thanks in advance.
EDIT:
#jaredad7 ~ That's what I've been trying, but it keeps causing the program to crash.
List box;
box.Append(items[items.size()].number, items[items.size()].weight);
This works just fine - no problems whatsoever.
The earlier code propagates a 1D vector of Item structs, which also works properly.
vector< List > boxes;
boxes[0].Append(items[items.size()].number, items[items.size()].weight);
This compiles fine but crashes during execution, no matter what index is used. (I'm also using couts for debugging, and the issue most definitely lies with trying to access the List functions.)
I'm suspecting that .push_back or somesuch may be needed, but I haven't been able to find much information concerning vectors of List objects.
If you can, my first suggestion would be to go with the vector (if that is allowed). As for accessing functions/attributes of a member of a vector, it's done the same way as an array, that is:
vectorname[i].functionname(a,b,c);
The best way to do this without vectors would be to use your nodes as the item container (a struct), and handle node-creation, deletion, etc. in your list class. Then, you would only really need one container for as many objects of one type as you need. You can make the type dynamic (although it appears you only need doubles for this project) by adding a class template (use google if you are unfamiliar with templates in C++). This will allow your user to make a container for each type of data (much like a vector).

getting mergesort to work on linked-list?

Apologies if this is a silly / simple question.. but I'm very lost. I'm having trouble getting this program to run. I've written this program to read in 2 values, the first being a number of elements in a linked list, and the second to be the maximum random value that can be put into each element.
It should then use the merge sort algorithm included to sort and reprint the sorted list.
Ok, so I'm getting errors like:
base operand of `->' has non-pointer type `LIST'
and
request for member `element' in `conductor', which is of non-aggregate type `LIST *'
...(and a few others).
Yes this is for a class.. I've written the program but I'm not sure what I've done wrong here or why I'm getting errors? Any help is appreciated! Thank you
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <sys/time.h>
using namespace std;
typedef struct LIST {
int element;
LIST *next;
};
LIST split(LIST list)
{
LIST pSecondCell;
if (list == NULL)
return NULL;
else if (list.next == NULL)
return NULL;
else {
pSecondCell = list.next;
list.next = pSecondCell.next;
pSecondCell.next = split(pSecondCell->next);
return pSecondCell;
}
}
LIST merge(LIST list1, LIST list2)
{
if (list1 == NULL)
return list2;
else if (list2 == NULL)
return list1;
else if (list1.element <= list2.element) {
list1.next = merge(list1.next, list2);
return list1;
} else {
list2.next = merge(list1, list2.next);
}
}
LIST MergeSort(LIST list)
{
LIST SecondList;
if (list == NULL)
return NULL;
else if (list.next == NULL)
return list;
else {
SecondList = split(list);
return merge(MergeSort(list), MergeSort(SecondList));
}
}
int main(int argCount, char *argVal[])
{
int i, number, max;
struct timeval time1;
struct timeval time2;
//check for correct number of arguments
if (argCount != 3) {
cout << "Incorrect number of arguments" << endl;
return 0;
}
// initialize read in n and max values
number = atoi(argVal[1]);
max = atoi(argVal[2]);
// create list and fill with random numbers
LIST *conductor;
LIST *root = new LIST;
conductor = root;
for (i = 0; i < number; i++) {
conductor.element = rand() % max;
conductor.next = new LIST;
conductor = conductor.next;
}
// time how long it takes to sort array using mergeSort
gettimeofday(&time1, NULL);
mergeSort(root);
gettimeofday(&time2, NULL);
// print name, sorted array, and running time
cout << "Heather Wilson" << endl;
conductor = root;
for (i = 0; i < number - 2; i++) {
cout << conductor.element << ", ";
conductor = conductor.next;
}
double micro1 = time1.tv_sec * 1000000 + time1.tv_usec;
double micro2 = time2.tv_sec * 1000000 + time2.tv_usec;
cout << conductor.element << endl;
cout << "Running time: " << micro2 - micro1 << " microseconds" << endl;
return 0;
}
For base operand of->' has non-pointer type LIST'
Replace the -> with a .. You want to access a member of a local LIST, not a member of a pointed at object.
request for memberelement' in conductor', which is of non-aggregate type LIST *
This is the opposite. Replace the . with a ->. You want to access a member of the pointed at LIST, not a member of the pointer.
For clarification, I didn't read the code. There's too much of it. But those are the usual ways to address those specific errors. parapura seems to have actually read the code.
First: you should never have let the code grow this big with so many errors. You should start small and simple, then build up, testing at every stage, and never add to code that doesn't work.
Here's a stripped-down beginning of your code, with some bugs fixed:
#include <iostream>
using namespace std;
typedef struct LIST{
int element;
LIST *next;
};
int main(){
int i, number, max;
number = 5;
max = 100;
// create list and fill with random numbers
LIST *conductor;
LIST *root = new LIST;
conductor = root;
for(i=0; i<number; i++){
conductor->element = rand() % max;
cout << "element " << i << " is " << conductor->element << endl;
conductor->next = new LIST;
conductor = conductor->next;
}
conductor = root; // Forgot this, didn't you!
for(i=0; i<number-2;i++){
cout << conductor->element << ", ";
conductor = conductor->next;
}
return 0;
}
Take a look at this, verify that it works, make sure you understand the changes I made, then you can take a crack at implementing your split, merge and MergeSort functions and the I/O (one at a time, and testing at every stage, naturally).
I think all the places you are passing
LIST merge ( LIST list1 , LIST list2 )
it should be
LIST* merge ( LIST* list1 , LIST* list2 )