1) I'm still trying to wrap my head around how linked lists work in c++. Currently I'm trying to insert a new node in between other nodes. Although I'm able to add the desired node, anything after that new node seems to be deleted once I print it:
void InsertNode(int pos, int val) {
Node *n = new Node();
n->data = val;
Node *pnt = head;
for (int i = 0; i < pos; i++) {
pnt = pnt->next;
}
pnt->next = n;
DisplayList();
}
2) And then I want to be able to create another operation that can search for an element in the list and output its position (if it exists). However from what I know so far I don't see how I can compare a value that I want to find to an element in a list.
Here's what I'd imagine it would look like, but I know the if statement isn't valid.
void SearchElement(int val) {
Node *list = head;
int i = 0;
while (list) {
list = list->next;
i++;
if (list == val) { cout << "The value is at position: " << i << endl; }
}
//print statement saying it doesn't exist
}
You have to append the rest of the list to n before you insert the new node:
n->next = pnt->next;
pnt->next = n;
For the second question: Your value is in list->data.
int i = 0;
while (list) {
if (list->data == val) {
cout << "The value is at position: " << i << endl;
break;
}
list = list->next;
i++;
}
Related
I am new to linked lists.My exercises are something like:"write a function which puts the value x to the end of your linked list".So , my code will look like this:(p is a pointer to the first value)
struct node
{
int info;
node *next;
};
void LastElement(int x , node * & p)
{
node *q = new node;
q = p;
while (q -> next != NULL)
q = q -> next;
q->next->info = x;
q->next->next = NULL;
}
My question is:How do i verify this program?What do i write in the main function?Will i create an array or...?
To simply test your code you can do a function like:
void check(node *p) {
while (p != nullptr) {
std::cout << p->info << std::endl;
}
}
But this function doesn't gonna work with your actual code, because when you do:
q->next->info = x;
q->next->next = NULL;
Your programme gonna crash, because q->next at this moment is null. If you wan't to add a new node whit the value x create a new one and put it in like:
// generate the need node
node *new_node = new node;
new_node->info = x;
// push the new node to the linked list
node->next = new_node;
But if you wan't to modify the last node do:
node->info = x;
// but not like you did:
// node->next->info = x;
You should write a test function that validates that the linked list is of the correct shape. That test function could, for example, walk your linked list in parallel with a std::vector and test that elements are the same pairwise and that the length is the same. Its prototype would be something like bool testEqual(node * list, std::vector<int>)
Now simply call LastElement a few times and then check that the resulting linked list is of the correct shape.
Here is a reference implementation, you can adapt it to arrays if you want:
bool testEqual(node * list, const std::vector<int>& test) {
for (int i = 0; i < test.size() && list != nullptr; i++)
if (test[i] != list->info) {
std::cerr << "mismatch at index " << i << std::endl;
return false;
}
list = list->next;
}
if (i == test.size() && list == nullptr) {
return true;
} else {
std::cerr << "list is too " << (list == nullptr ? "short" : "long" ) << std::endl;
return false;
}
}
Simply call this as testEqual(theList, {1,2,3,4,5}).
I have a list and I want to display it's values.
I want to see 1 2 3 4, but I have a endless loop like 1 2 3 4 1 2 3 4 1 2..
Can't understand, why?
struct node
{
int item;
node *next;
node(int x, node *t)
{
item = x;
next = t;
}
};
int main()
{
node *firstElement = new node(1, NULL);
firstElement->next = firstElement;
node *lastElement = firstElement;
for (int i = 2; i < 5; i++)
lastElement = (lastElement->next = new node(i, firstElement));
for (node *first = lastElement; first != 0; first = first->next)
cout << first->item << " ";
delete firstElement;
return 0;
}
Try using this code:
struct node
{
int item;
node *next;
node(int x, node *t)
{
item = x;
next = t;
}
};
int main()
{
node *firstElement = new node(1, NULL);
node *lastElement = firstElement;
for (int i = 2; i < 5; i++)
lastElement = (lastElement->next = new node(i, nullptr));
for (node *first = firstElement; first != 0; first = first->next)
cout << first->item << " ";
return 0;
}
IdeOne live code
The problem is that you set the "next" link of your last node to this node itself, not nullptr.
Also, it's better to delete the memory allocated
The problem is that your data structure has an infinite loop in itself: this line
firstElement->next = firstElement;
makes firstElement point back to itself, creating a circular list. When you add more elements, your list remains circular, so exit condition first == 0 is never achieved.
If you want your list to remain linear, not circular, your insertion code should be modified as follows:
node *firstElement = new node(1, NULL);
node *lastElement = firstElement;
for (int i = 2; i < 5; i++) {
lastElement->next = new node(i, lastElement->next)
lastElement = lastElement->next;
}
The printing code should start with firstElement:
for (node *current = firstElement; current != 0; current = current->next)
cout << current->item << " ";
Finally, deleting a single firstItem is not sufficient. You need a loop to traverse the whole list. Alternatively, you could chain deletion in the destructor by calling delete next, but this is dangerous, because recursive invocation of destructors may overflow the stack.
You have a loop in your list, because lastElement->next always points to firstElement. This is why first will never be equal to 0.
If you really need a loop I think you should write something like this:
node* p = firstElement;
do {
cout << p->item << " ";
p = p->next;
} while (p != firstElement);
The problem is that you create every node with firstElement as its next.
This would make sense if you were adding nodes to the front of the list, but you're adding them at the back, so the last node will point back to the start.
Since you're adding to the back, terminate the list on every insertion instead:
lastElement->next = new node(i, nullptr))
Hi guys for my lab assignment this week I was assigned to learn about Linked Lists. The lab prompt is as follows:
Write a program that creates a forward linked list of at least 20 elements, where each element holds a random integer between 0 and 99. Print the list.
Write the function "returnMiddleList" to find the middle element of the linked list in one pass. Print the integer value of this element and the position of this element (starting at zero) in relation to the head (where the head = 0, the element pointed to by the head = 1, the element pointed to by the previous one = 2, etc).
Split the list in half at the middle element to create two entirely separate* linked lists of near equal size (+/- 1) and print the two lists. Modify the "returnMiddleList" function to accomplish this, returning the head of the second linked list and setting the link of the element pointing to that head to null. Then print the two sums of the integers stored in the elements of both lists.
Sort the two lists from least to greatest and print them out (printing at this step is optional depending on the sort approach taken). Then combine the two lists while sorting them again from least to greatest and print out the new list. (HINT: you can subdivide the lists further and sort them on a scale of one to two element lists before sorting and combining the first two unsorted lists. What is this sort called?)
I have got #1 and #2 working, but #3 and #4 is where the issue is beginning. When I split my link list into two lists and print the individual lists out, my first link list prints out 9 numbers when it should be printing out 10 (the 10th number somehow disappears?), but when I do the sum of the first list right after that, the number that has disappeared gets added in the sum! I do not know why it is disappearing, and this is one issue. Another issue is in the second list, a random "0" gets added to the list and one of the numbers is lost. My last issue is about #4 as the merge algorithm I have used does not seem to work (I am merging the list together while sorting them, but I am not using a recursion sort because we have not learned that yet). Any input and help would be greatly appreciated! Thanks!
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
struct nodeType {
int data;
nodeType *link;
};
void populateList(nodeType *head) {
// srand(time(NULL));
nodeType *temp;
nodeType *current = head;
for (int i = 0; i < 20; i++) {
temp = new nodeType;
current->data = rand() % 100;
current->link = temp;
current = temp;
}
temp->link = NULL;
}
void print(nodeType *head) {
int i = 1;
while (head->link != NULL) {
cout << "#" << i++ << ": " << head->data << endl;
head = head->link;
}
}
nodeType* returnMiddleList(nodeType *head) {
nodeType *p1 = head, *p2 = head;
int count = 0;
int middle = 1;
while (p1->link->link != NULL) {
p1 = p1->link;
count++;
if (count % 2 == 0) {
p2 = p2->link;
middle++;
}
}
cout << "Middle #" << middle << ": " << p2->data << endl;
p1 = p2->link;
p2->link = NULL;
return p1;
}
void add(nodeType *head) {
int sum = 0;
while (head != NULL) {
sum = sum + head->data;
head = head->link;
}
cout << sum << endl;
}
void sort(nodeType *head) {
nodeType *temp = head;
while (temp != NULL) {
nodeType *temp2 = temp;
while (temp2 != NULL) {
if (temp->data > temp2->data) {
int temp3;
temp3 = temp->data;
temp->data = temp2->data;
temp2->data = temp3;
}
temp2 = temp2->link;
}
temp = temp->link;
}
}
nodeType* merge(nodeType* head1, nodeType* head2) {
nodeType *head3 = new nodeType, *current1 = head1, *current2 = head2;
while (current1 != NULL || current2 != NULL) {
if (current1 == NULL) {
while (current2 != NULL) {
//logic
current2 = current2->link; //dumps list 2
head3->data = current2->data;
}
break;
}
if (current2 == NULL) {
while (current1 != NULL) {
//Logic
current1 = current1->link; //dumps list 1
head3->data = current1->data;
}
break;
}
if (current1->data < current2->data) {
//logic
current1 = current1->link; //increments list 1
head3->data = current1->data;
} else {
//logic
current2 = current2->link; //increments list 2
head3->data = current2->data;
}
}
return head3;
}
int main() {
nodeType *head = new nodeType, *head2, *head3;
populateList(head);
print(head);
cout << endl;
head2 = returnMiddleList(head);
cout << endl << "List #1 Sum: ";
add(head);
cout << endl << "List #2 Sum: ";
add(head2);
sort(head);
cout << endl << "List #1 Sorted" << endl;
print(head);
sort(head2);
cout << endl << "List #2 Sorted" << endl;
print(head2);
head3 = merge(head, head2);
print(head3);
}
For #3, you don't need a count. The code should also include checks for head == NULL, p1 == NULL before attempting to check p1->link, and it should check for p1->link == NULL before attempting to check p1->link->link. After adding these checks, to eliminate the count, just advance p1 two at a time: p1 = p1->link->link, while advancing p2 one at a time: p2 = p2->link. Once you reach the end of the list with p1->link or p1->link->link, then consider p2 to be a pointer to the last node of the first half of the list, and follow the given instructions on how to split the list.
For #4, the approach of recursively splitting the list into sub-lists is generically known as a divide and conquer algorithm (wiki link). This approach is used for top down merge sort, and although there are other approaches which are better suited (faster) to implementing merge sort with linked lists, I get the sense that the instructor probably wants you to follow the given hints.
#include <iostream>
#include<string>
using namespace std;
struct nodeType
{
int info;
nodeType *next;
};
class linkedListType
{
private:
nodeType *first, *last;
int length;
public:
linkedListType()//constructor
{
first = last = NULL;
length = 0;
}
void print() // normal print
{
nodeType * current = first;
while (current != NULL)
{
cout << current->info <<" ";
// update statement
current = current ->next;
}
}
void insertEnd(int item) //insert item to the end of the list
{ // forward insertion
nodeType* newNode = new nodeType;
newNode ->info = item;
if (length == 0)
{
first = last = newNode;
newNode->next = NULL;
}//if
else
{
last->next = newNode;
last = newNode;
newNode->next = NULL;
}// else
length++;
}
}
void clearList()
{
nodeType * current;
while ( first != NULL)
{
current = first;
first = first->next;
delete current;
length--;
}// while
~linkedListType() //destroctor
{
clearList();
}
> `
//
Blockquote i cant write this method emplement please anyone help me and explane why ////////////////////////////////////////////////////////////////////
/this method. can anyone help ma to write it to me and explan why/
////////////////////////////////////////////////////////////////////
`
void printReverse() /*this is the function that i cant understand it or complete it. this function print elements in the list in reverse*/
{
nodeYype* current=last ,*newnode =new nodType ;
for(int i=length;i>=0;i--)
//i cant complete this method
}
};
void main()
{
linkedListType list1;
list1.insertEnd(12); //insert item
list1.insertEnd(25);//insert item
list1.insertEnd(18);//insert item
list1.insertEnd(37);//insert item
list1.insertEnd(60);//insert item
list1.insertEnd(100);//insert item
list1.insertEnd(37);//insert item
list1.insertEnd(37);//insert item
list1.insertEnd(37);//insert item
list1.insertEnd(60);//insert item
list1.insertEnd(25);//insert item
list1.insertEnd(100);//insert item
list1.insertEnd(25);//insert item
cout <<"Printing the linked list elements\n";
list1.print();
cout <<"\nPrinting the list elements in reverse order\n";
list1.printReverse();
}
void nodeType::PrintListReverse()
{
if (next)
next->PrintListReverse();
std::cout << info << std::endl;
}
Recursively find the end of the list, printing on return.
(I'm only enabling you because I'm bored)
Alternatively:
void linkedListType::PrintList()
{
std::vector<int> info(length);
nodeType* curNode = first;
for (int i = 0; curNode != NULL; i++, curNode = curNode->next)
{
info[i] = curNode->info;
}
for (int i = length-1; i >=0; i--)
{
std::cout << info[i] << std::endl;
}
}
If you can write a recursive function to traverse the list in proper order, printing it in reverse order is a snap.
There are two possibilities. Either to write a recursive function or rebuild your list in the reverse order. That is before printing the list you either create a new list on the base pf existent or rebuild the original list itself.
You already have a loop that decrements i from length to 0. Based on i, you can traverse the list and print the node that you reached. Fine tune for off by 1 errors so that you actually print from last to first and don't print when the list is empty.
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;
}
}
}
}