Reverse the elements of a list using pointers [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to read a singly linked list backwards?
Reverse a LinkedList c++
How can I reverse the elements of a connected list without using arrays
(I have to use only pointers thats my problem).

You need neither to swap node content or a stack. If you want to reverse a single-linked list just walk it with a pair of pointers plus on intermediate pointer within the iterative loop. Don't forget to update the head pointer when you're finished;
void reverse_list(node **head)
{
node *cur=NULL, *nxt=NULL;
if (!(head || *head || (*head)->next))
return;
nxt = *head;
while (nxt != NULL)
{
node *prv = cur;
cur = nxt;
nxt = nxt->next;
cur->next = prv;
}
*head = cur;
}
Assuming the list node is something like this:
typedef struct node
{
..data..
struct node *next;
} node;
and it is properly managed, then you invoke as such:
node *head = NULL;
...fill the list...
reverse_list(&head);

Treat the list like a stack, pop the elements off and push them into a new list.

Conside a list called lst which allows us to move forward backward i.e it is doubly linked list
You can reverse the list lst by simply swapping the content of the beginning and the end nodes
void reverse(lst *beg,lst *end)
{
lst temp;
while(beg!=end)
{
//swap the content of the nodes
*temp=*beg;
*beg=*end;
*end=*temp;
beg=beg->Next();//move to next node
end=end->prev();//move to previous node
}
}
OR
If its a singly linked list,you can use stack
void reverse(lst* beg)
{
stack<lst*> stc;
lst* temp=beg;
lst* temp1=beg;
while(temp)//store pointers to lst nodes in stack
{
stc.push(temp);
temp=temp.Next();
}
while(temp1)//pop the stack by inserting it into list from beginning
{
*temp1=*stc.top();
temp1=temp1.Next();
stc.pop();
}
}

Related

Indexed singly linked list

I want to create a singly linked list with. I already have an implementation that does not permit indexing on it.
I would like to add this feature but I am not sure how to do that.
So basically the head should have index "1". But I can't figure it out myself what am I supposed to do in If statement to increase the index by 1 each step.
void AddNode (int addData)
{
nodePtr NewNode = new node;
NewNode->next = NULL;
NewNode->data = addData;
if (head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = NewNode;
NewNode->index;
}
else
{
head = NewNode;
NewNode->index = 1;
}
}
You mean for the ability to do something like get a linked list node via a get(index)?
Also, your head should not have index 1, it should be 0. This does not comply with standard practice of zero-based indexing.
A linked list does not technically have indexes nor should it store them. It seems like a linked list might not be the right data structure for what you are doing, however you can treat it like so with a loop like this (excuse if my c++ syntax is rusty)
int get(int index) {
Node current = head;
for (int x = 0; x < index; x++) {
if (current->next == null) {
//some sort of error handling for index out of bounds
} else {
current = current->next;
}
}
return current->data
}
get(2) would return the 3rd element of the list.
Graph for the structure
Why do you want to add it to the end of the list? Just simply add the new node to the front.
I don't think it is necessary to follow the order of 1,2,3.... Instead, you can do it reversely
Before you add a new node, you visit the head and find the index(i)of it. When you add the new one, the index of this one will be i+1.
Two advantages:
- It doses not change anything when you loop through this list.
- You know how many you have added into this list.
So what you really want to do is to add the ability to index elements of a linked list.
There is no need to actually store the index anywhere (as you don't really store the index of an array/vector element as the type and the address of the first element of the array is everything you need to retrieve the i-th element).
The only information you want to keep is the length of the list since computing it is costly because you have to traverse the list from head to tail every time you need it. Once you have this information the addNode should only update the size of the list.
As you already know accessing the i-th elements of a linked list is also costly (compared to a vector), but it is easy to code.
Something like the following should work:
void get(Node* head, size_t pos) {
while (head && pos--)
head = head->next;
return pos<=0 ? head : nullptr ;
}
It traverses the list from the head until it either reaches the end (head is nullptr) or pos is <=0.
Once you are out of the loop if pos>0 means that the list is shorter than pos otherwise you can return head (which will point to the pos-th element)

Using an array of pointers-to-pointers to manipulate the pointers it points to (C++)

I've been doing this as an exercise on my own to get better at C++ (messing around with a linked list I wrote). What I want to do is to reverse the list by twisting the pointers around, rather than just 'printing' the data out in reverse (which is relatively straightforward).
I have an array of pointers-to-pointers, each pointing to a node in a linked list. But this is less a question about linked-list dynamics (which I understand), and more about pointer magick.
A node looks like this,
template<class T>
struct node {
T data;
node *next;
node(T value) : data(value), next(nullptr) {}
};
And the code in question,
node<T> **reverseArr[listLength];
node<T> *parser = root;
for (auto i : reverseArr) {
i = &parser;
parser = parser->next;
}
root = *(reverseArr[listLength - 1]);
for (int ppi = listLength - 1; ppi >= 0; --ppi) {
if (ppi == 0) {
(*reverseArr[ppi])->next = nullptr;
//std::cout << "ppi is zero!" << "\t";
}
else {
(*reverseArr[ppi])->next = (*reverseArr[ppi - 1]);
//std::cout << "ppi, 'tis not zero!" << "\t";
}
}
My logic:
The new root is the last element of the list,
Iterate through the array in reverse,
Set the current node's next pointer to the previous one by setting the current node's nextNode to the next node in the loop.
What's happening:
If I leave the debug print statements commented, nothing. The function's called but the linked list remains unchanged (not reversed)
If I uncomment the debug prints, the program seg-faults (which doesn't make a whole lot of sense to me but seems to indicate a flaw in my code)
I suspect there's something I'm missing that a fresh pair of eyes might catch. Am I, perhaps, mishandling the array (not accounting for the decay to a pointer or something)?
You're overthinking the problem. The correct way to reverse a single-linked list is much simpler than you think, and does not involve arrays at all.
All you need to do is walk through the list setting each node's next pointer to the head of the list, then set the head of the list to that node. Essentially, you are unlinking each node and inserting it at the start of the list. Once you reach the end, your list is reversed.
It just requires a bit of care, because the order that you do things is important. Something like this should do it:
template <class T>
node<T> * reverse( node<T> * head )
{
node<T> *current = head;
head = NULL;
while( current != NULL )
{
// store remainder of list
node<T> *remain = current->next;
// re-link current node at the head
current->next = head;
head = current;
// continue iterating remainder of list
current = remain;
}
return head;
}
The operation has a linear time complexity. You would invoke it by passing your list's head node as follows:
root = reverse( root );
It should go without saying that it would be a bad idea to call this function with any node that is not the head of a list, or to pass in a list that contains cycles.

Sort Ascending - Linked List [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm having a little trouble with getting my head around how this function would work and what I need to do. I have int number as my data type and node* next in my node class. I also have node pointers head, current and temp. My question is how would I go about getting my list of integers into order? Also how does ascending and decending work in a single linked list?
My header file:
#ifndef SDI_LL
#define SDI_LL
namespace SDI
{
class LinkedList
{
class Node
{
public:
int number; //data element
Node* next; //pointer to next, node inside each node
private:
};
private:
Node *head;
Node *current; //head, current and temp node pointers
Node *temp;
public:
LinkedList(); //constructor to access nodes from above
~LinkedList(); //destructor
void insert(int add);
void remove(int remove); //functions that access private data nodes above
void display();
void reverse();
void search(int searchNum);
void sortAscending();
void sortDecending();
void saveAll();
void restoreAll();
};
}
#endif
My ascending function so far where it starts from the beginning and searches through the list:
void LinkedList::sortAscending()
{
current = head;
for (current = head; current;)
{
temp = current;
current = current->next;
}
}
In general, you should use containers available in the standard libraries, which provide efficient sorting methods where applicable.
That said, if you want to do it for learning purposes - as you probably "should at least once" - then it is not too difficult to implement.
for (current = head; current;)
That's a funny for loop, personally I'd prefer:
current = head;
while(current) // or current != nullptr to be more explicit
Note also that you (unnecessarily, of course) assign head to current twice - immediately before the for loop, and in the initialisation of it.
A simple scheme (but not at all efficient!) might be to just swap 'out of order' elements as you iterate through the list, until no swaps were necessary:
bool changeMade;
do{
changeMade = false;
current = head;
while( current ){
temp = current;
current = current->next;
if( current && current->data < temp->data ){
changeMade = true;
swap( temp->data, current->data );
}
}
} while( changeMade );
This assumes a data field is the only other in the node - since it doesn't actually swap the nodes, just the data. (Doing the former is not really any more difficult - but without seeing your node type declaration I'd be making up names and risk confusing the issue.)
I don't see any declarations for current, head, and temp, but I assume they are pointers to node. Have you decided on a sort algorithm? Does the sort algorithm need to be efficient or is something with the performance of a bubble sort ok? With logic similar to a bubble sort, you can repeatedly move the node with the largest value to the end of the list. Or to save a bit of time, you could remove the node with the largest value from the original list and insert it into the front of a new list that would end up in sorted order. More efficient algorithms use logic based on merge sort.
To remove or swap nodes, using a pointer to pointer can avoid special handling for the first node of a list (the one pointed to by pList in this example):
NODE * SortList(NODE * pList)
{
NODE * pNew = NULL; /* sorted list */
NODE **ppNode; /* ptr to ptr to node */
NODE **ppLargest; /* ptr to ptr to largest node */
NODE * pLargest; /* ptr to largest node */
while(pList != NULL){ /* while list not empty */
ppLargest = &pList; /* find largest node */
ppNode = &((*ppLargest)->next);
while(NULL != *ppNode){
if((*ppNode)->data > (*ppLargest)->data)
ppLargest = ppNode;
ppNode = &((*ppNode)->next);
}
pLargest = *ppLargest; /* move node to new */
*ppLargest = pLargest->next;
pLargest->next = pNew;
pNew = pLargest;
}
return(pNew);
}

obtain the address of a node given a node address in a linked list

So I have a pretty good understanding of iterating through a linked list, and also obtaining the next node in the list. Now I trying to go in the other direction, but I soon realized its not as easy as it appears. Unlike an array where you can iterate forwards and backwards. I seem to be stumped.
So If I have a list of 1 -> 2 -> 3 -> 4 -> NULL How would I go about obtaining the address of node 2 given the location of node 3?
I started messing around with this code below which returns all items up to node 3. I just don't see how I can get that previous node? By the way searchList() returns the address of a node if you give it the node->data value. Using the list above searchList(3) returns the address of the node which has 3 as its data member.
struct node {
int data;
node* next;
};
void llclass::getPrevious() {
node *stop = searchList(nodeItem),
*start = head;
while (start != stop) {
cout << start->data << endl;
start = start->next;
}
}
With a singly-linked list like yours, it is not possible to obtain the address of node 2 if you're given only the address of node 3. You would have to start at the head node and iterate forward until reaching 3, keeping track of the previous node (2 in this case). Alternately, you could use a doubly-linked list that includes a "node *previous;" member.
Sounds like you want to get the previous node of a node whose value is given as input to you. This should do that for you:
node* llclass::getPrevious(int item)
{
node* previous = NULL;
node* current = head;
while(current)
{
if (current->data == item)
{
return previous;
}
else
{
previous = current;
current = current->next;
}
}
return NULL;
}

What is the pointer-to-pointer technique for the simpler traversal of linked lists? [duplicate]

This question already has answers here:
An interesting C linked list idiom
(11 answers)
Closed 5 years ago.
Ten years ago, I was shown a technique for traversing a linked list: instead of using a single pointer, you used a double pointer (pointer-to-pointer).
The technique yielded smaller, more elegant code by eliminating the need to check for certain boundary/edge cases.
Does anyone know what this technique actually is?
I think you mean double pointer as in "pointer to a pointer" which is very efficient for inserting at the end of a singly linked list or a tree structure. The idea is that you don't need a special case or a "trailing pointer" to follow your traversal pointer once you find the end (a NULL pointer). Since you can just dereference your pointer to a pointer (it points to the last node's next pointer!) to insert. Something like this:
T **p = &list_start;
while (*p) {
p = &(*p)->next;
}
*p = new T;
instead of something like this:
T *p = list_start;
if (p == NULL) {
list_start = new T;
} else {
while (p->next) {
p = p->next;
}
p->next = new T;
}
NOTE: It is also useful for making efficient removal code for a singly linked list. At any point doing *p = (*p)->next will remove the node you are "looking at" (of course you still need to clean up the node's storage).
By "double-pointer", I think you mean "pointer-to-pointer". This is useful because it allows you to eliminate special cases for either the head or tail pointers. For example, given this list:
struct node {
struct node *next;
int key;
/* ... */
};
struct node *head;
If you want to search for a node and remove it from the list, the single-pointer method would look like:
if (head->key == search_key)
{
removed = head;
head = head->next;
}
else
{
struct node *cur;
for (cur = head; cur->next != NULL; cur = cur->next)
{
if (cur->next->key == search_key)
{
removed = cur->next;
cur->next = cur->next->next;
break;
}
}
}
Whereas the pointer-to-pointer method is much simpler:
struct node **cur;
for (cur = &head; *cur != NULL; cur = &(*cur)->next)
{
if ((*cur)->key == search_key)
{
removed = *cur;
*cur = (*cur)->next;
break;
}
}
I think you mean doubly-linked lists where a node is something like:
struct Node {
(..) data // The data being stored in the node, it can be of any data type
Node *next; // A pointer to the next node; null for last node
Node *prev; // A pointer to the previous node; null for first node
}
I agree with the comments about using the STL containers for handling your list dirty work. However, this being Stack Overflow, we're all here to learn something.
Here's how you would normally insert into a list:
typedef struct _Node {
void * data;
Node * next;
} Node;
Node * insert( Node * root, void * data ) {
Node * list = root;
Node * listSave = root;
while ( list != null ) {
if ( data < list->data ) {
break;
}
listSave = list;
list = list->next;
}
Node * newNode = (Node*)malloc( sizeof(Node) );
newNode->data = data;
/* Insert at the beginning of the list */
if ( listSave == list ) {
newNode->next = list;
list = newNode;
}
/* Insert at the end of the list */
else if ( list == null ) {
listSave->next = newNode;
newNode->next = null;
list = root;
}
/* Insert at the middle of the list */
else {
listSave->next = newNode;
newNode->next = list;
list = root;
}
return list;
}
Notice all the extra checking you have to do depending on whether the insertion occurs at the beginning, end or middle of the list. Contrast this with the double pointer method:
void insert( Node ** proot, void * data ) {
Node ** plist = proot;
while ( *plist != null ) {
if ( data < (*plist)->data ) {
break;
}
plist = &(*plist)->next;
}
Node * newNode = (Node *)malloc( sizeof(Node) );
newNode->data = data;
newNode->next = *plist;
*plist = newNode;
}
As Evan Teran indicated, this works well for singly linked lists, but when it's doubly linked, you end up going through just as many if not more manipulations as the single pointer case. The other draw back is that you're going through two pointer dereferences for each traversal. While the code looks cleaner, it probably doesn't run as quickly as the single pointer code.
You probably mean a doubly-linked list, with one of the pointers going forward and the other going backward. This allows you to get to the next and previous nodes for a given node without having to remember the last one or two nodes encountered (as in a singly-linked list).
But the one thing I discovered which made the code even more elegant was to always have two dummy elements in the list at all times, the first and the last. This gets rid of the edge cases for insertion and deletion since you're always acting on a node in the middle of the list.
For example, an empty list is created:
first = new node
last = new node
first.next = last
first.prev = null
last.next = null
last.prev = first
// null <- first <-> last -> null
Obviously, traversing the list is slightly modified (forward version shown only):
curr = first.next
while curr <> last:
do something with curr
curr = curr.next
The insertions are much simpler since you don't have to concern yourself with whether you're inserting at the start or end of the list. To insert before the current point:
if curr = first:
raise error
add = new node
add.next = curr
add.prev = curr.prev
curr.prev.next = add
curr.prev = add
Deletions are also simpler, avoiding the edge cases:
if curr = first or curr = last:
raise error
curr.prev.next = curr.next
curr.next.prev = curr.prev
delete curr
All very much cleaner code and at the cost of only having to maintain two extra nodes per list, not a great burden in today's huge memory space environments.
Caveat 1: If you're doing embedded programming where space still might matter, this may not be a viable solution (though some embedded environments are also pretty grunty these days).
Caveat 2: If you're using a language that already provides linked list capabilities, it's probably better to do that rather than roll your own (other than for very specific circumstances).