Specifically, the goal here is to create a linked structure that has some number of nodes, between 5 and 2 million. Don’t worry that this number is large or that values may wrap around past the max size of integer. If you have created your linked structure correctly, a modern computer can breeze through this code very quickly. Notice that the comments describe exactly how this main should work. Here are the highlights:
Create three loops
The first loop creates the linked structure, hooking together the “next” fields of each node and giving each node an integer value between 0 and the randomly chosen size.
The second loop adds up all of the nodes and counts them. Counting the nodes in this case should be used only as check to make sure you are not missing one.
The third loop traverses all nodes again, this time deleting them.
Node.h
class Node {
public:
Node();
Node(const Node& orig);
virtual ~Node();
bool hasNext();
Node* getNext();
void setNext(Node* newNext);
int getValue();
void setValue(int val);
private:
Node* next;
int value;
};
#endif
Node.cpp
include "Node.h"
include <iostream>
Node::Node() {
next = NULL;
}
Node::Node(const Node& orig) {
next = orig.next;
value = orig.value;
}
Node::~Node() {
}
bool Node::hasNext(){
if (next != NULL)
return true;
else
return false;
}
Node* Node::getNext(){
return next;
}
void Node::setNext(Node* newNext){
if(newNext == NULL)
next = NULL;
else
next = newNext->next;
}
int Node::getValue(){
return value;
}
void Node::setValue(int val){
value = val;
}
main.cpp
include <cstdlib>
include <iostream>
include "Node.h"
include <time.h>
using namespace std;
int main(int argc, char** argv) {
//This is the node that starts it all
Node *tail;
Node* head = new Node();
//select a random number between 5 and 2,000,000
srand(time(NULL));
int size = (rand() % 2000000) + 5;
int total = 0;
int counter = 0;
//print out the size of the list that will be created/destroyed
cout << "The total size is: " << size << endl;
head->setValue(0);
tail = head;
Node *newNode = new Node;
for (int i = 1; i < size; i++){
Node *newNode = new Node;
newNode->setValue(i);
newNode->setNext(NULL);
tail->setNext(newNode);
tail = newNode;
}
//Create a list that counts from 0 to 2,000,000
//Link all of the nodes together
//A for loop is easiest here
cout << head->getNext()->getValue();
Node* current = head;
while (current != NULL){
counter += current->getValue();
cout << current->getValue();
current = current->getNext();
total++;
}
//Traverse the list you created and add up all of the values
//Use a while loop
//output the number of nodes. In addition, print out the sum
//of all of the values of the nodes.
cout << "Tracked " << total << " nodes, with a total count of " << counter << endl;
//Now loop through your linked structure a third time and
//delete all of the nodes
//Again, I require you use a while loop
cout << "Deleted " << total << " nodes. We're done!" << endl;
return 0;
}
It is printing out the total size then...
I am getting a Seg fault:11.
I am also missing some parts in the main, I am confused on how to write these as well.
it should be next = newNext; instead of next = newNext->next;
void Node::setNext(Node* newNext){
if(newNext == NULL)
next = NULL;
else
next = newNext;
}
First of all, avoid using getter functions in your Abstract Data Type. Those should be reserved for your client test application; keep them out of your ADT. Instead, pass any values in as parameters as re: the prototype. Second, avoid void returning methods in your classes. Rather, return a bool or int. Zero or false for error, and true or some non-zero integer for your success message.
That aside, I was looking up ways to use classes to build nodes, and your post came up. Interesting start. We'll see where we go with this.
Ciao,
Lewsutt
Related
I'm working on circular doubly linked list. For example I have three values in it
1 2 3
and I'm passing it into method where I insert 0 in the middle, like that:
1 0 2 3
I wonder if it's possible somehow to return it back, but with pointer's moved to this 0 value instead of standard start on 1 value? If not, how would you do an 'actual position' pointer to this list, which shows where nodes were deleted/inserted?
//Edit
There I'm adding my code
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int allCharCounter = 0;
struct List_node{
int value;
struct List_node *next;
struct List_node *prev;
};
void insert(List_node** start, int v){
List_node* newNode = new List_node;
newNode->value = v;
if(*start == NULL){
newNode->next = newNode;
newNode->prev = newNode;
*start = newNode;
}else{
newNode->next = *start;
newNode->prev = (*start)->prev;
(*start)->prev->next = newNode;
(*start)->prev = newNode;
}
}
//This method should insert a node after node where the pointer was
//With value smaller by 1 -> (c-1)
//after insertion pointer should be moved 'c' times
void insertAndMove(List_node** POS){
if((*POS)->next = NULL){
return;
}else{
int c = (*POS)->value;
//cout << c << endl;
List_node* newNode = new List_node;
newNode->value = c-1;
(*POS)->next = newNode;
newNode->prev = *POS;
newNode->next = (*POS)->next;
(*POS)->next->prev = newNode;
//List_node* current;
//there I planned to move my list
for(int i = 0; i < c; i++){
//*POS = (*POS)->next;
//cout <<"POS: " << (*POS)->value << endl;
}
}
}
int getNumber(){
int c = getchar();
int value = 0;
for(; (c < 48 || c > 57); c = getchar());
for(; c > 47 && c < 58 ; c = getchar()){
value = 10*value+c-'0';
allCharCounter++;
}
return value;
}
int main(){
int numberOfOperations = getNumber();
struct List_node* list = NULL;
while(!feof(stdin)){
int number = getNumber();
insert(&list, number);
}
insertAndMove(&list);
cout << list->value << endl;
}
I'm sorry if I don't described the problem and assumptions clearly. I have already asked a question where I vastly desribe it. There should be better overview what I want to achieve:
Self-organising sequence of numbers with big amount of operations on it - best data structure
If it is circular doubly linked list, then you can just move all the elements before the inserted element to end of the list [a1,a2,a3,a4] -> [a1,a2,new,a3,a4]->[new,a3,a4,a1,a2]
The pointer will be at new but it still is the same list.
I hope it'll be helpful
It would be easy enough to have your list head be a pointer-to-pointer and set that to your new list head. The thing to keep in mind with a circular list is that you need to keep track of some starting point so you know when you have gone through the entire list, but that starting point does not itself need to be stable so long as you are aware that it can change.
I'm writing this function as part of homework. Wouldn't be such a big deal if there were a tail pointer included and most of the code was provided by my instructor and included in an object file, so I don't have the implementation to include. Anyway, for some reason the base case in my function never gets reached. Can anyone tell me why this keeps looping?
#include "clist.h"
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
};
//Iteratively compute and return the number of nodes in the circular linked list
int count(node* head)
{
int nodeTotal = 1;
node* temp = head;
while(temp->next != head)
{
nodeTotal++;
temp = temp->next;
}
return nodeTotal;
}
//Recursively compute and return the number of nodes in the circular linked list
int countR(node* head)
{
node* temp = head;
if(temp->next == head)
return 0;
else
return 1 + countR(temp->next);
}
//Iteratively compute and return the sum of the ints contained in the circular linked list
int sum(node* head)
{
int valuesTotal = 2;
node* temp = head;
while(temp->next != head)
{
valuesTotal += temp->data;
temp = temp->next;
}
return valuesTotal;
}
int main()
{
node* head{nullptr};
/* Builds a circular linked list with a random number of nodes
*containing randomly-chosen numbers.
*/
build(head);
display(head);
// PUT YOUR CODE HERE to call the functions assigned,
// and print out the results. For example,
//
// cout << "iterative sum: " << sum(head) << endl;
//
// The code for your functions should be in clist.cpp.
cout << "\nIterative node count: " << count(head) << endl;
cout << "Iterative sum: " << sum(head) << endl;
cout << "Recursive node count: " << countR(head) << endl;
// When called the 2nd time, this also prints the total
// of the numbers in the nodes.
display(head);
int nNodesFreed{0};
node* n{head};
node* temp;
while( n != head || ! nNodesFreed) {
temp = n->next;
delete n;
n = temp;
nNodesFreed++;
}
cout << "# nodes freed: " << nNodesFreed << endl;
//destroy(head);
return 0;
}
Your stopping condition isn't working because each time you make a recursive call, you start with a new head pointer. So, let's say you start with a linked list like this:
On the first call, you pass A (well, the address of A), and it checks whether A == B. It doesn't, so it does a recursive call passing B. On that call, it checks whether B == C. That fails, so it does a recursive call passing C. That checks whether C == D. That fails, so it checks whether D == E. That fails, so it checks whether E == A. That fails, so it checks whether A == B. That still fails, so it continues...
And round and round it goes. Where it stops, nobody knows!
So hey, I'm having a problem with this project I have. I'm supposed to read integers from a file and insert them into a list. There's a findSpot function that needs to be implemented that traverses the linked list and if the next node's value is larger than what is being checked, it returns the current "spot". And then we output the linked list to a separate file.
Here's the code.
#include <iostream>
#include <fstream>
using namespace std;
class listNode {
public:
int value;
listNode* next;
friend class linkedList;
listNode()
: value(0)
, next(NULL)
{
}
public:
~listNode(){
};
};
class linkedList {
listNode* listHead;
public:
linkedList()
: listHead(NULL)
{
}
bool isEmpty()
{
return (listHead == 0);
}
void listInsert(int data, listNode* spot)
{
listNode* newNode;
newNode->value = data;
newNode->next = NULL;
if (isEmpty()) {
listHead = newNode;
}
else {
newNode->next = spot->next;
spot->next = newNode;
cout << newNode;
}
}
/*void listDelete ()
{
}*/
listNode* findSpot(int data)
{
listNode* spot;
spot = listHead;
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
return spot;
}
void printList(listNode* spot)
{
listNode* newNode = spot;
while (newNode != NULL) {
cout << "Inserting " << newNode->value << ": "
<< "listHead-->(" << newNode->value << "," << newNode->next->value << ")-->(";
newNode = newNode->next;
}
cout << endl;
}
/*~linkedList()
{
listNode* temp = spot->next;
spot->next = spot->next->next;
delete temp;
}*/
};
int main(int argc, char* argv[])
{
int data;
listNode* spot;
ifstream infile;
infile.open(argv[1]);
ofstream outfile(argv[2]);
cout << "Reading Data from the file" << endl;
while (infile >> data) {
cout << data << endl;
}
infile.close();
linkedList myList;
infile.open(argv[1]);
while (infile >> data) {
myList.findSpot(data);
myList.listInsert(data, spot);
myList.printList(spot);
}
cout << "Printing your linked list to the output file.";
/*while (outfile.is_open())
{
myList.printList();
}*/
infile.close();
outfile.close();
return 0;
}
I don't know if the problem lies mainly in the insertList function or if it's the findSpot function. The findSpot function seems correct to me but I may just be missing something.
As I run the code, the actual reading of the file the first time is fine. Actually inserting anything into the linked list causes the program to hang.
Ok, lets try this again. I'll actually include some code, but please try to use this as a learning point, and not something to just copy paste. I know you said you were copying your teachers algorithm, but what they gave you is probably just that, an algorithm. It is your job to actually implement that in working code, checking for error conditions, etc. Anyway, here we go:
For the function findSpot:
listNode* linkedList::findSpot(int data) {
listNode* spot = listHead; // Initialize spot to start of list
if ( isEmpty() ) // if list is empty, return NULL
return NULL;
// now we know listHead isn't null, so look through the list and
// find the entry that has a value greater than the one provided
// return the list item BEFORE the one with the greater value
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
// return the one we found; This could be the same as listHead
// (start of list), something in the middle, or the last item on the
// list. If we return from here, it will not be NULL
return spot;
}
Now we can do the insert function:
void linkedList::listInsert(int data, listNode* spot) {
// We need a new item to put on the list, so create it
listNode* newNode = new listNode();
newNode->value = data;
newNode->next = NULL;
// If the list is empty, update the head to point at our new object
if ( isEmpty() ) {
listHead = newNode;
// otherwise point spot to new item, and new item to the one spot
// pointed to
} else {
newNode->next = spot->next;
spot->next = newNode;
}
}
Looking at your print function, that is going to have it's own issues. It looks like you want to print the whole list, but it seems that you are starting to print from "spot". It's all very confused. It also has an issue using newNode->next->value, without checking if newNode->next is NULL. Here's a short example of what I think you are trying to do... note that I don't even need to pass in spot, just the data point added:
void linkedList::printList(int data) {
// if some huckleberry called this before calling insert,
// list will be empty... always a good idea to check
if ( isEmpty())
return;
// first line of output... just print out the data point
// added and start of output text
cout << "Inserted " << data << ": " << "listHead-->(";
// start at start of list
listNode* newNode = listHead;
// loop through until we find the end
while (newNode != NULL) {
cout << newNode->value; // print the value
newNode = newNode->next; // move to the next item on the list
// We moved to the next node; It might be NULL and the loop will end
// if not, we want to print an open bracket since we know another one
// is going to be printed
if ( newNode != NULL )
cout << ")-->(";
}
// last item was just printed, so close off the last bracket
cout << ")" << endl;
}
Hope that is somewhat helpful
Since this looks like a homework assignment, I'm going to give you one fix:
change
myList.findSpot(data);
to
spot = myList.findSpot(data);
If you look closely, spot is used, but never assigned anything.
Well, there are several problems with your program (besides formatting). In the function findSpot(), you have:
listNode* spot;
spot = listHead;
while (spot->next != 0 && spot->next->value < data) {
spot = spot->next;
}
return spot;
The problem here is that the first time you call this, listHead is NULL, so the
while (spot->next
is going to fail, since spot is NULL.
I also notice that nowhere in your code do you call new(). In listInsert, you need to use new() to initialize your newNode variable.
Lastly, find spot has 2 conditions where it can return NULL. If the list is empty, it should return NULL, and you would want to insert at the start of the list. If the new value you are adding is greater than all the others, you will also return NULL and you would have to add to the end of the list.
Since this is a homework assignment, I don't want to write the code for you, but hopefully that helps.
Ok my program randomly draws cards out of a deck and stores them in an array of linked lists. one list for each suit and the list holds the rank.
struct node{
node(int value = 0) {data=value; next = NULL; }
int data;
node *next;
};
class list{
public:
list ();
~list();
bool empty() const {return N == 0;}
bool full() const {return false;}
int size() const {return N;}
void resize(int);
void clear();
void insert(int);
void remove(int);
void pop_back() { remove(N-1);}
const int & back();
int & operator[](int);
int findNodeRank(int);
friend ostream& operator<<(ostream &out, list);
private:
int N;
node *head;
node *findnode(int);
};
list::list() {
cout << "making list" << endl;
head = new node;
cout << "made list" <<endl;
}
My main function has these lines
cout << "here 1" << endl;
list deck[4];
cout << "not here 1";
I get the following output after i compile and run my code.
here 1
making list
made list
making list
made list
making list
made list
making list
made list
not here 1
before loopHere;
insert
after find node rank
before find node
after find node
[1] 11472 segmentation fault (core dumped) ./Prog2b
As you can see it never gets out of making the list array because not here is never called. I dont understand whats going wrong.
OK ive narrowed it down to this function. Ill try to post all relevant code
if (i == 0){
node *p = new node(rankIndex);
cout << "before find node" << endl;
node *pp = findnode(N);
cout << "after find node" << endl;
p->next = pp->next;
pp->next = p;
N++;
}else {
prev->next = match->next;
match->next = head->next; .
head->next = match;
}
}
int list::findNodeRank(int rankIndex){ //Function similar to findnode that checks for rank match. Returns the index of the match.
if (head->next == 0)
return 0;
node *p = head->next;
int i = 1;
cout << "find node rank function" << endl;
while(p->data != 0){
if (p->data == rankIndex)
return i;
p = p->next;
i++;
}
return 0; //Returns 0 if there is no match
}
inline
node *list::findnode(int i) {
if (i == -1)
return head;
node *p = head->next;
while(i--)
p = p->next;
return p;
}
Im probably referencing a node that hasn't been created yet or something. Im bad with these linked lists. Ok basically the program like i said draws random cards and stores the results in these lists ive created. The insert function is supposed to add the card to the end of the list if its never been drawn. If the cards been drawn its supposed to move it to the front of the list. Any ideas??
I'm trying to wrap my head around how to write an algorithm to sort a linked list, but I'm having a hard time coming up with something that will work. What we need to do have a linked list that contains a name in a string, and an int for hours. After displaying the list and the sum of the hours, we then have to sort the list in ascending order by the hours in a queue. I have the list and all it's functioned stored in a class object, as you will see. I cleared the whole function of what I had in hopes of coming up with a fresh idea but nothing is coming to mind. I initially was going to create a second linked list that had the sorted list, but then I began to wonder if it was possible to sort it within the same list. Here is my code as of posting.
#include <iostream>
#include <ctime>
using namespace std;
// OrderedLL class
template<class T>
class OrderedLL
{
private:
struct NODE
{
string sName;
int sHours;
NODE *next;
};
NODE *list;
NODE *rear;
public:
// Constructor
OrderedLL () { list = rear = NULL;}
// Insert item x -------------------------------------
void Insert(string x, int y)
{
NODE *r;
// Create a new node
r = new(NODE); r->sName = x; r->sHours = y;
r->next = NULL;
// Inserts the item into the list
r->next = list;
list = r;
}
// Display the linked list --------------------------
void display()
{ NODE *p = list;
while( p != NULL)
{ cout << p->sName << "/" << p->sHours << "-->"; p = p->next;}
cout << "NULL\n";
}
// Delete x from the linked list --------------------
void DeleteNode(T x)
{
NODE *p = list, *r = list;
while( p->info != x) {r=p; p=p->next; }
if( p == list)
{ // delete the first node
list = p->next; delete(p);
}
else
{ r->next = p->next; delete(p);}
}
// Sort by hours ------------------------------------
void sortHours()
{
NODE *p, *q;
}
// Display the total hours --------------------------
friend T totHours(OrderedLL LL)
{
NODE *p;
int total = 0;
p = LL.list;
while(p != NULL)
{
total += p->sHours;
p = p->next;
}
cout << "Total spending time = " << total << endl;
}
}; // end of OrderedLL class
int main(void)
{
// Declare variables
time_t a;
OrderedLL<int> unsortedLL;
OrderedLL<int> sortedLL;
int inHours;
string inName;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
// Asks the user to enter a name and hours 5 times, inserting each entry
// into the queue
for(int i = 0; i < 5; i++)
{
cout << "Enter name and Time: ";
cin >> inName >> inHours;
unsortedLL.Insert(inName, inHours);
}
// Displays the unsorted list
cout << "\nWaiting List-->";
unsortedLL.display();
totHours(unsortedLL);
// Calls for the function to sort the list into a queue by hours
unsortedLL.sortHours();
unsortedLL.display();
return 0;
} // End of "main"
As always thanks to anyone who can help
Try sorting the linked-list like you are sorting an integer array. Instead of swapping the nodes, swap the contents inside the nodes.
If you don't care about efficiency you can use any sorting algorithm. What's different between linked lists and arrays is that the swap operation, to swap the position of two elements while sorting, will be a lot slower because it has to run through the links of the list.
An O(n²) bubble sort is easy to implement with a linked list since it only swaps an element with its neighbor.
If you care about efficiency you can look into implementing the merge sort algorithm even if it's a little more complicated.
You should insert like this
void Insert(string x, int y)
{
NODE *r;NODE *temp;
// Create a new node
r = new NODE; r->sName = x; r->sHours = y;r->next = NULL;
if(list==null)//check if list is empty
{
list=r;//insert the node r in the list
}
else
{
temp=list;
while(temp->next!=null)temp=temp->next;//reach to the end of the list
temp->next=r;//insert it at the end of the list
}
}
No need of rear pointer..just check if list->next is null,if yes you are at the end
and your sorthour function should be
void sortHours()
{
for(NODE* n=list;n->next!=null;n=n->next)//get each of the node in list 1 by 1 except the last one i.e. n
{
for(NODE* n1=n->next;n1!=null;n1=n1->next)//compare the list n node with all the nodes that follow it i.e.n1
{
if(n->sHours > n1->sHours)//if one of the node is the less than n
{
//swap n and n1
node temp=*n;
n->age=n1->age;
n->name=n1->name;
n1->age=temp.age;
n1->name=temp.name;
}
}
}
}