How to reverse linked list using double pointer?
I was learning about double pointers and thought if we can reverse linked list using one pointer only.
Conversion to using a pointer to pointer left as an exercise for the reader. Also has some distinct shortcomings in terms of style.
#include <iostream>
struct node {
int data;
node *next;
};
node *reverse(node *list) {
node *prev = NULL;
node *next;
while (list) {
next = list->next;
list->next = prev;
prev = list;
list = next;
}
return prev;
}
void show_list(node *list) {
while (list != NULL) {
std::cout << list->data << ", ";
list = list->next;
}
}
int main() {
node *list = NULL;
for (int i=0; i<10; i++) {
node *n = new node;
n->next = list;
n->data = i;
list = n;
}
std::cout << "As built: ";
show_list(list);
list = reverse(list);
std::cout << "Reversed: ";
show_list(list);
return 0;
}
If you decide to modify a pointer you received as a parameter, it's probably easier to deal with a reference to a pointer than a pointer to a pointer though.
Related
I'm currently working on a class project where we make a linked list and we're supposed to create a function that clears the list then deletes it (with "delete LIST_NAME;"). I have implemented the function as instructed by my professor, also forcing the list to become null after the delete. The function works within itself, but when it returns to the main function, the list gets a new value.
Is this sort of function just not possible in C++?
#include <iostream>
struct Node
{
int val;
Node* next;
};
struct LinkedList
{
int count;
Node* head;
Node* tail;
};
void Clear(LinkedList* list) {
Node* node = list->head;
Node* next = nullptr;
while (node != nullptr) {
next = node->next;
delete node;
node = next;
}
list->head = nullptr;
list->tail = nullptr;
list->count = 0;
}
void Destroy (LinkedList* list) {
Clear(list);
delete list;
list = nullptr;
std::cout << "\n(should be) Destroyed";
}
int main() {
//creating a list element
Node* node = new Node;
node->val = 'a';
node->next = nullptr;
//inserting the element onto list
LinkedList* list = new LinkedList;
list->count = 0;
list->head = node;
list->tail = node;
std::cout << "\nList: " << list;
Destroy(list);
std::cout << "\nList: " << list;
std::cout << "\nEND";
}
This is just a snip of my code but it shows what I mean. Using the debugger the list has the value 0x0 by the end of the function but in the main function it's assigned a new value as shown by the debugger.
You take list by value so it's local to the function.
If you'd like to make changes to it that are visible at the call site, take it by reference:
// `list` is now a reference to the pointer at the call site:
void Destroy(LinkedList*& list) {
Clear(list);
delete list;
list = nullptr; // this now sets the referenced `LinkedList*` to `nullptr`
std::cout << "\n(should be) Destroyed";
}
I am having trouble in C++ putting and displaying array into a linked list. I'm having lots of trouble with linked lists in general
Here is my code. It only displays the first number. (It should display 19 21 17 22 33)
#include <iostream>
using namespace std;
struct node {
int age;
node *next;
};
void display(node *t)
{
node *temp = t;
cout << temp->age << " ";
}
int main()
{
int Age[5] = { 19, 21, 17, 22, 33 };
node* List = new node;
List = NULL;
node* temp2 = List;
while (temp2 != NULL)
{
temp2 = temp2->next;
node* List = new node;
List = NULL;
node* temp2 = List;
}
for (int i = 0; i < 5; i++)
{
temp2 = new node;
temp2 -> age = Age[i];
temp2 -> next = NULL;
if (List == NULL)
List = temp2;
}
display(List);
system("PAUSE");
return 0;
}
Take the following code as an example. Note that you have to delete all created nodes at the end of program to avoid memory leaks.
#include <iostream>
#include <cstddef>
using namespace std;
struct node {
int age;
node* next;
};
void display(node* list) {
while (list != NULL) {
cout << list->age << ' ';
list = list->next;
}
}
node* create(int age) {
node* t = new node;
t->age = age;
t->next = NULL;
return t;
}
void add(node* list, node* t) {
while (list->next != NULL) {
list = list->next;
}
list->next = t;
}
void release(node* list) {
while (list != NULL) {
node* t = list;
list = list->next;
delete t;
}
}
int main() {
int arr[5] = { 19, 21, 17, 22, 33 };
node* list = create(arr[0]);
for (int i = 1; i < 5; i++) {
node* t = create(arr[i]);
add(list, t);
}
display(list);
release(list);
system("PAUSE");
return 0;
}
There's a lot going on here. I'd recommend you look through some tutorials to help solidify your understanding of pointers and linked lists.
To answer your question, let's step through what's happening:
In your main function, you dynamically allocate a node object and have List point to this object. Then, you set List to NULL. When you initialize the node pointer temp2 to List, temp2 also points to NULL.
Because temp2 = NULL, you skip over the following while loop.
In the first iteration of your for loop, you re-assign temp2 to a newly created object, then set the age for that node to the Age[0]. When we get to your if statement, List = NULL so we enter the conditional statement and set List to temp2 where temp2->age = Age[0].
For each additional iteration of your for loop, List no longer is equal to NULL so you never enter your if statement again. List still points to the node where age = Age[0].
When you get to your display function, assuming it was written to loop through a linked list, your List pointer is a list with one node where age = 19. Assuming your had a linked list with multiple valid nodes, your display() function doesn't iterate over them.
I was working on a homework assignment with linked lists, and while it seems that the code itself is spitting out the "right" answer (what the teacher wants it to), it brings up an error message when running that states "the program has stopped working (it will be forced closed, reported to windows, etc)". The program doesn't force close after closing this dialogue, and besides this, seems to be exactly what my teacher is looking for in the assignment. Any suggestions?
#include <iostream> // Provides cout
#include <cstdlib> // Provides EXIT_SUCCESS
using namespace std; // Allows all standard library items to be used
struct node
{
int data;
node* link;
};
void insert_at_head(node*& head, int entry)
//Precondition: head is the head pointer of a linked list, entry is
// a non-negative integer
//Postcondition: Inserts a new node with data field set to entry at the
// beginning of the linked list head
{
node* n;
n = new node;
n->data = entry;
n->link = head;
head = n;
}
void print(const node* head)
//Precondistion: head is the head pointer of a linked list
//Postcondition: Prints that linked list
{
const node* cursor;
cout << "The linked list is:" << endl;
for (cursor=head; cursor != NULL; cursor=cursor->link)
cout << cursor-> data << " ";
cout << endl;
}
void delete_last(node* & head)
{
while (head->link != NULL)
{
int i;
for(i = 0; 10 >= i; i++)
{
struct node* secondlast = head;
struct node* last = head->link;
while(last->link != NULL)
{ struct node* t = last;
secondlast = t;
last = last->link;
}
delete last;
secondlast->link = NULL;
cout << "I have deleted the last element in the linked list" << endl;
print(head);
}
}
while (head == NULL)
{
return;
}
}
int main( )
{ int i;
node* head;
head = NULL;
for(i = 1; 10 >= i; i++)
{
insert_at_head(head, i);
}
print(head);
delete_last(head);
return EXIT_SUCCESS;
}
I got a problem with my doubly linked list. How can i make the input unique ( i don`t want it to be repeated )
for example i can input 1 and then again 1 i will have a list of 1 and 1. I need to forbid this somehow :) so the list can contain only not repeating numbers.
#include <cstdlib>
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
node* prev;
};
class Node
{
public:
Node();
~Node();
void setKopa();
void printForward();
private:
node* head;
node* tail;
node* n;
};
Node::Node()
{
setKopa();
}
Node::~Node()
{
delete n;
}
void Node::setKopa()
{
int lenght;
do
{
cout << "Input list lenght (how many elements): ";
cin >> lenght;
if(lenght<2)
cout << "Error list has to have atleast 2 elements!" <<endl;
}
while(lenght<2);
int fill;
cout << "Input "<< lenght <<" elements: "<<endl;
for (int i=0; i<lenght; i++)
{
cin>>fill;
n = new node;
n->data = fill;
if (i==0)
{
n->prev = NULL;
head = n;
tail = n;
}
else if (i+1==lenght)
{
n->prev = tail;
tail->next = n;
tail = n;
tail->next = NULL;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
}
void Node::printForward()
{
node* temp = head;
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp-> next;
}
cout << endl;
}
int main()
{
Node a;
a.printForward();
system("pause");
return 0;
}
When you read input, go through the list to see if the input is already there.
With that (simple) answer out of the way, I would like to address some other things regarding your code. The first is that you have a memory leak in that you never delete the list. The second is that you don't need the class member variable n, it might as well be a local variable inside the setKopa loop.
Your way of adding new nodes is also, well, weird. It should, in my opinion, be more general instead of using the loop counter to check what to do. What I suggest is that you make a member function to add new nodes, taking the integer data as argument. This way you can call this function to add nodes anywhere, and not just in the setKopa function. In fact, I think the list should not handle that input at all, instead it should be a free-standing function called from main and which calls the addNode function.
Also the node structure doesn't need to be in the global namespace, it could be a private structure in the Node class. And speaking of the Node class, shouldn't it really be called List instead?
So if I may suggest, you might want to do something like this:
#include <iostream>
class List
{
public:
List()
: head(nullptr), tail(nullptr)
{}
~List();
void addNode(const int data);
void printAll() const;
private:
struct node
{
node()
: next(nullptr), prev(nullptr)
{}
node* next;
node* prev;
int data;
};
node* head;
node* tail;
};
List::~List()
{
for (node* next, *cur = head; cur; cur = next)
{
next = cur->next;
delete cur;
}
}
void List::addNode(const int data)
{
node* n = new node;
n->data = data;
if (tail == nullptr)
{
// First node in list
head = tail = n;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
void List::printAll() const
{
std::cout << "{ ";
for (node* cur = head; cur != nullptr; cur = cur->next)
std::cout << cur->data << ' ';
std::cout << "}\n";
}
int main()
{
List list;
for (int i = 0; i < 10; ++i)
list.addNode(i);
list.printAll();
}
The above code should print
{ 0 1 2 3 4 5 6 7 8 9 }
Replace the node-adding loop with your own.
I am using merge_lists function to merge two lists (for ultimately merge sort). It gets compiled but when I run it, it freezes. Please help whats wrong?
node* merge_lists(node* list1,node* list2){
node* t;
node* temp1;
if(list1==NULL){
return list2;
}
else if(list2==NULL){
return list1;
}
if(((list1->head)->word)<=((list2->head)->word)){
t->head=list1->head;
temp1->head=list1->head->next;
t->next=merge_lists(temp1,list2);
}
else{
t->head=list2->head;
temp1->head=list2->head->next;
t->next=merge_lists(list1,temp1);
}
return t;
}
Please note that my class node is defined as follows:
class node{
public:
string word;
node *next;
node *head;
};
Your freeze/crash is likely because you are dereferencing the t pointer without first initializing it. This causes undefined behavior. (A good compiler will emit a warning when you use an uninitialized variable.)
You need to assign a valid pointer to t before attempting to dereference it.
The same issue is present with the temp1 pointer.
You are using pointers t and temp1 without assigning values to them. Freezing is only one of many possibilities.
Here are some comments:
You use t and temp1 before it has been allocated. You should do node* t = new node(); at the beginning.
Why does your node have both head and word? I would eliminate head and just have each node with a word and a next. The head of your list would be either t, list1, or `list2.
Here is a working example:
Node:
class node{
public:
string* word;
node *next;
};
Merge:
node* merge_lists(node* list1,node* list2) {
if(list1==NULL) {
return list2;
} else if (list2==NULL) {
return list1;
}
// Create a new list to hold the merged result.
node* t;
if (*(list1->word)<=*(list2->word)) {
t = list1;
list1 = list1->next;
} else {
// Use list2
t = list2;
list2 = list2->next;
}
// Merge the remainder of the lists.
t->next = merge_lists(list1, list2);
}
Utilities:
node* make_list(string strings[], int len, int pos=0) {
node *list = NULL;
if (pos < len) {
list = new node();
list->word = &(strings[pos]);
list->next = make_list(strings, len, pos+1);
}
return list;
}
void display_list(node* list) {
while (list != NULL) {
cout << *(list->word) << "->";
list = list->next;
}
cout << "." << endl;
}
int main(int argc, char* argv[]) {
string s1[] = {"b", "d"};
string s2[] = {"a", "c", "e"};
node* l1 = make_list(s1, 2);
node* l2 = make_list(s2, 3);
cout << "List 1: ";
display_list(l1);
cout << "List 2: ";
display_list(l2);
node* sorted = merge_lists(l1, l2);
cout << "Merged: ";
display_list(sorted);
}