Finding cycle in singly linked list - c++

Finding a cycle in singly linked list and find the node from where cycle starts.
I have seen use of two pointers( generally slow and fast) to find the cycle but I have written this code and it seems to be working fine. My question is, is there something my code is missing out on, while finding the cycle in singly linked list.
Node* find_cycle_node(Node *head){
Node *p=head;
Node *q;
while(p->next!=null)
{
q=p->next;
while(q->next!=null)
{
if(p==q) return q; //Node repeated i.e cycle
else (q=q->next;)
}
p=p->next;
}
return null; // no cycle detected
}

Your inner loop will not terminate if there is cycle which is a couple nodes down the handle, e.g., it will be an infinite loop for something like this:
1 -> 2 -> 3 -> 4 -> 5
^ |
| |
+---------+

How about this ?
struct Node_
{
int ix ;
struct Node_* next ;
} ;
typedef struct Node_ NODE ;
NODE *head = NULL ;
int main()
{
NODE* n1 ;
n1 = (NODE*) malloc(sizeof(NODE)) ;
n1->ix = 0 ;
n1->next = NULL ;
head = n1 ;
NODE* n2 ;
n2 = (NODE*) malloc(sizeof(NODE)) ;
n2->ix = 1 ;
n2->next = NULL ;
n1->next = n2 ;
NODE* n3 ;
n3 = (NODE*) malloc(sizeof(NODE)) ;
n3->ix = 2 ;
n3->next = NULL ;
n2->next = n3 ;
NODE* n4 ;
n4 = (NODE*) malloc(sizeof(NODE)) ;
n4->ix = 3 ;
n4->next = n2 ;
n3->next = n4 ;
unordered_map<NODE*,int> hashx ;
int idx ;
NODE* p = head ;
while(p != NULL)
{
hashx[p] += 1 ;
if(hashx[p] >= 2)
{
printf("node p (%d) recycle !!\n",p->ix);
break ;
}
p = p->next ;
}
printf("done \n") ;
} //main

is there something my code is missing out on
return; // no cycle detected
This line looks pretty bad, it should be changed to s.th. like
return NULL; // no cycle detected

To me your inner loop condition appears to be ambiguous. You are analysing if (p==q) where q is p-> next. this means that the node p previously considered didn't haD A CYCLE. So to me your inner loop wil never terminate.
you must consider this:-
#include <iostream>
using namespace std;
class Node{
public:
int data;
Node * next;
Node(int x){
data = x;
next = NULL;
}
Node(int x, Node * y){
data = x;
next = y;
}
};
class linkedList{
Node *head;
public:
linkedList(){
head = NULL;
}
void addNode(int value){
Node *p;
if(head == NULL)
head = new Node (value, NULL);
else{
p = head;
while(p->next !=NULL)
p=p->next;
p->next = new Node (value, NULL);
}
}
void print(){
Node * p;
p = head;
while(p != NULL){
cout << p->data;
p = p->next;
}
}
int findCycle(){
Node *p, *start, *q;
p = head;
while(p != NULL){
q = p->next;
while (q != NULL ){
if(p->data == q->data)
return q->data;
else
q = q->next;
}
p = p->next;
}
return 0;
}
};
int main(){
linkedList l1;
l1.addNode(1);
l1.addNode(2);
l1.addNode(3);
l1.addNode(4);
l1.addNode(5);
l1.addNode(3);
int node = l1.findCycle();
cout<<node;
return 0;
}
What do you say people about this code.

void LinkListOps::createCycledListAndFindACycleNode()
{
// build a list with a cycle in it
ZNODE* head = new ZNODE(0);
ZNODE* current = head;
ZNODE* cycle = 0;
for (int i = 1; i < 8; i++)
{
current->_next = new ZNODE(i);
current = current->_next;
if (i == 6)
cycle = current;
if (i == 7)
current->_next = cycle;
}
// verify that there is a cycle
ZNODE* slow = head;
ZNODE* fast = head;
ZNODE* cycleNode = 0;
while (slow && fast && fast->_next)
{
slow = slow->_next;
fast = fast->_next->_next;
if (slow == fast)
{
cycleNode = slow;
break;
}
}
if (cycleNode == 0)
{
printf("No cycle\n");
return;
}
// finally find a cycle node which will be p2
ZNODE* p1 = head;
ZNODE* p2 = cycleNode;
while (1)
{
for (p2 = cycleNode; p2->_next != cycleNode; p2 = p2->_next)
{
if (p2 == p1)
break;
}
if (p2 == p1)
break;
p1 = p1->_next;
}
printf("%d\n", p2->_i);
}

You can quickly find out if there is a loop in a linked list by doing the following:
ptr = head;
current = nullptr;
if (!ptr) {
current = ptr->next;
while(current && current!=ptr) {
current = current->next;
if (current) {
current = current->next;
}
ptr = ptr->next;
}
}
At the end of this, if current is not null, then a loop was found, and current will be somewhere inside of it. This works by iterating current twice as fast through the list as ptr, and will always find a loop, if any exists, before ptr has looped once.

Related

Cloning a linked list where each node has a random pointer to any other node in linked list

Please help me find what is wrong with my code
(1).
You are given a Singly Linked List with N nodes where each node next pointing to its next node. You are also given M random pointers , where you will be given M number of pairs denoting two nodes a and b i.e. a->arb = b.
The task is to complete the function copyList() which takes one argument the head of the linked list to be cloned and should return the head of the cloned linked list.
NOTE : If their is any node whose arbitrary pointer is not given then its by default null.
I tried to write code for the above problem..but it is not working
// { Driver Code Starts
#include <bits/stdc++.h>
using namespace std;
struct Node {
int data;
Node *next;
Node *arb;
Node(int x) {
data = x;
next = NULL;
arb = NULL;
}
};
void print(Node *root) {
Node *temp = root;
while (temp != NULL) {
int k;
if (temp->arb == NULL)
k = -1;
else
k = temp->arb->data;
cout << temp->data << " " << k << " ";
temp = temp->next;
}
}
Node *copyList(Node *head);
void append(Node **head_ref, Node **tail_ref, int new_data) {
Node *new_node = new Node(new_data);
if (*head_ref == NULL) {
*head_ref = new_node;
} else
(*tail_ref)->next = new_node;
*tail_ref = new_node;
}
bool validation(Node *head, Node *res, Node *cloned_addr,
Node *generated_addr) {
if (generated_addr == cloned_addr) return false;
Node *temp1 = head;
Node *temp2 = res;
int len1 = 0, len2 = 0;
while (temp1 != NULL) {
len1++;
temp1 = temp1->next;
}
while (temp2 != NULL) {
len2++;
temp2 = temp2->next;
}
/*if lengths not equal */
if (len1 != len2) return false;
temp1 = head;
temp2 = res;
while (temp1 != NULL) {
if (temp1->data != temp2->data) return false;
if (temp1->arb != NULL and temp2->arb != NULL) {
if (temp1->arb->data != temp2->arb->data) return false;
} else if (temp1->arb != NULL and temp2->arb == NULL)
return false;
else if (temp1->arb == NULL and temp2->arb != NULL)
return false;
temp1 = temp1->next;
temp2 = temp2->next;
}
return true;
}
/* Driver program to test above function*/
int main() {
int T, i, n, l, k;
Node *generated_addr = NULL;
/*reading input stuff*/
cin >> T;
while (T--) {
generated_addr = NULL;
struct Node *head = NULL, *tail = NULL;
cin >> n >> k;
for (i = 1; i <= n; i++) {
cin >> l;
append(&head, &tail, l);
}
for (int i = 0; i < k; i++) {
int a, b;
cin >> a >> b;
Node *tempA = head;
int count = -1;
while (tempA != NULL) {
count++;
if (count == a - 1) break;
tempA = tempA->next;
}
Node *tempB = head;
count = -1;
while (tempB != NULL) {
count++;
if (count == b - 1) break;
tempB = tempB->next;
}
// when both a is greater than N
if (a <= n) tempA->arb = tempB;
}
/*read finished*/
generated_addr = head;
Node *res = copyList(head);
Node *cloned_addr = res;
cout << validation(head, res, cloned_addr, generated_addr) << endl;
}
return 0;
}
// } Driver Code Ends
/* the node structure is as follows
struct Node {
int data;
Node *next;
Node *arb;
Node(int x) {
data = x;
next = NULL;
arb = NULL;
}
};
*/
// Should return the head of the copied linked list the
// output will be 1 if successfully copied
Node *copyList(Node *head) {
if(!head)
return nullptr;
Node*q=head;
Node*clone=new Node(q->data);
clone->next=0;
clone->arb=q->arb;
Node*p=clone;
Node*r=q;
q=q->next;
while(q)
{
r->next=p;
p->next=new Node(q->data);
p=p->next;
p->next=0;
p->arb=q->arb;
r=q;
q=q->next;
}
r->next=p;
p=clone;
while(p)
{
if(p->arb)
p->arb=p->arb->next;
p=p->next;
}
return clone;
}
The pointers inside the list cannot be assigned until you have constructed the cloned list itself, because until then the nodes to point will not exist.
Therefore, you need two iterations: the first one to clone the list and make a dictionary that associates the original node with the clone, and the second one to update the pointers. The code would look like this:
Node *copyList(Node *head) {
if(!head)
return nullptr;
Node* it1 = head;
Node* clone = new Node;
Node* it2 = clone;
std::map<Node*, Node*> nodeDict;
nodeDict[nullptr] = nullptr;
// first iteration: create the list and the values
while(it1){
it2->data = it1->data;
nodeDict[it1] = it2;
it1 = it1->next;
it2->next = it1 ? new Node: nullptr;
it2 = it2->next;
}
// second iteration: connect the nodes
it1 = head;
it2 = clone;
while(it1){
it2->arb = nodeDict[it1->arb];
it1 = it1->next;
it2 = it2->next;
}
return clone;
}

Dynamic allocated lists - create a function that deletes all the elements which contain an even value

As I homework, I have to create a program which deletes all the nodes which contain an even value.
Here is how I've done it:
#include <iostream>
using namespace std;
struct node {
int info;
node* next;
};
void sterge(node*& p)
{
node* t;
t = new node;
if (p->info % 2 == 0)
{
p = p->next;
}
t = p;
while (t != NULL)
{
if (t->next != NULL)
{
if (t->next->info % 2 == 0)
{
node* aux;
aux = t->next;
t->next = t->next->next;
delete aux;
}
}
t = t->next;
}
}
int main()
{
node* head = new node;
head->info = 5;
node* p = new node;
node* t = new node;
t->info = 2;
head->next = t;
p = head;
node* x = new node;
x->info = 4;
node* w = new node;
w->info = 6;
t->next = x;
x->next = w;
w->next = nullptr;
sterge(head);
//Loop through the list and print each value
while (p != NULL) {
cout << p->info << endl;
p = p->next;
}
return 0;
}
But the output for the nodes created in main is 5 and 4.
I know the reason why but I don't know how to fix it.
Basically, I verify the next node if it has an even value, and then go to the next node. So it would look like this:
5 -> next is even so 2 is deleted
-> go to the next node which is 4
^now the problem is that this node is not being checked because I always check the next one. So it is considered by the program valid.
So how can I fix my program?
Put a continue after your delete.
That way, the next iteration will begin immediately, without the rest of the current iteration being executed, so the unwanted t = t->next will be skipped.

How do I sort Linked list based on the length of strings? [duplicate]

I have been struggling for hours on end with this problem. My goal is to sort a linked list using only pointers (I cannot place linked list into vec or array and then sort). I am given the pointer to the head node of the list. The only methods i can call on the pointers are head->next (next node) and head->key (value of int stored in node, used to make comparisons). I have been using my whiteboard excessively and have tried just about everything I can think of.
Node* sort_list(Node* head)
{
Node* tempNode = NULL;
Node* tempHead = head;
Node* tempNext = head->next;
while(tempNext!=NULL) {
if(tempHead->key > tempNext->key) {
tempNode = tempHead;
tempHead = tempNext;
tempNode->next = tempNode->next->next;
tempHead->next = tempNode;
tempNext = tempHead->next;
print_list(tempHead);
}
else {
tempHead = tempHead->next;
tempNext = tempNext->next;
}
}
return head;
}
Since it's a singly linked list, we can do: (psuedo code)
bool unsorted = true;
while(unsorted) {
unsorted = false;
cur = head;
while(cur != nullptr) {
next = cur->next;
if(next < cur) {
swap(cur, next)
unsorted = true;
}
cur = cur->next;
}
}
I know its late but I also search for it but didn't get one so I make my own. maybe it will help someone.
I am using bubble sort (kind of sort algorithm) to sort data in a single linked list. It just swapping the data inside a node.
void sorting(){
Node* cur1 = head;
Node* cur2 = head;
for (int i = 0; i < getSize(); i++) {
for (int j = 0; j < getSize() - 1; j++) {
if (cur1->data < cur2->data) {
int temp = cur1->data;
cur1->data = cur2->data;
cur2->data = temp;
}
cur2 = cur2->next;
}
cur2 = head;
cur1 = head->next;
for (int k = 0; k < i; k++) {
cur1 = cur1->next;
}
}
}
Don't feel bad this is a lot harder than it sounds. If this were in an array it would be considerably easier. If the list were doubly linked it would be easier. Take a look at this code, it implements an insertion sort
struct Node {
int key;
Node *next;
} *NodePtr;
// do a simple selection sort http://en.wikipedia.org/wiki/Selection_sort
Node* sort_list(Node* head) {
Node *top = nullptr; // first Node we will return this value
Node *current = nullptr;
bool sorted = false;
while (sorted == false) {
// we are going to look for the lowest value in the list
Node *parent = head;
Node *lowparent = head; // we need this because list is only linked forward
Node *low = head; // this will end up with the lowest Node
sorted = true;
do {
// find the lowest valued key
Node* next = parent->next;
if (parent->key > next->key) {
lowparent = parent;
low = next;
sorted = false;
}
parent = parent->next;
} while (parent->next != nullptr);
if (current != nullptr) { // first time current == nullptr
current->next = low;
}
// remove the lowest item from the list and reconnect the list
// basically you are forming two lists, one with the sorted Nodes
// and one with the remaining unsorted Nodes
current = low;
if (current == head) { head = current->next; }
lowparent->next = low->next;
current->next = nullptr;
if (top == nullptr) {
top = current;
}
};
current->next = head;
return top;
}
int _tmain(int argc, _TCHAR* argv []) {
Node nodes[4];
nodes[0].key = 3;
nodes[1].key = 4;
nodes[2].key = 5;
nodes[3].key = 1;
nodes[0].next = &nodes[1];
nodes[1].next = &nodes[2];
nodes[2].next = &nodes[3];
nodes[3].next = nullptr;
auto sortedNodes = sort_list(&nodes[0]);
return 0;
}
Use a recursive approach as it is the easiest way of dealing with linked structures:
Pseudocode:
SORT(head)
if (head->next == null)
return
tempNode = head->next
SORT(tempNode)
if (tempNode->value < head->value)
SWAP(head, tempNode)
SORT(head)
return
so the let's say you have 5 4 3 2 1
1) 5 4 3 1 2
2) 5 4 1 3 2
3) 5 4 1 2 3
4) 5 1 4 2 3
5) 5 1 2 4 3
...
n) 1 2 3 4 5
Assume the Node like this:
struct Node
{
Node *next;
int key;
Node(int x) : key(x), next(NULL) {}
};
use insertion sort algorithm to sort the List:
Node* sort_list(Node* head)
{
Node dumy_node(0);
Node *cur_node = head;
while (cur_node)
{
Node *insert_cur_pos = dumy_node.next;
Node *insert_pre_pos = NULL;
while (insert_cur_pos)
{
if (insert_cur_pos->key > cur_node->key)
break;
insert_pre_pos = insert_cur_pos;
insert_cur_pos = insert_cur_pos->next;
}
if (!insert_pre_pos)
insert_pre_pos = &dumy_node;
Node *temp_node = cur_node->next;
cur_node->next = insert_pre_pos->next;
insert_pre_pos->next = cur_node;
cur_node = temp_node;
}
return dumy_node.next;
}
int swapNode( node * &first, node * &second)
{
//first we will declare the
//previous of the swaping nodes
node *firstprev=NULL;
node*secprev=NULL;
node*current=head;
//set previous first
while(current->next!=first)
{
current=current->next;
}
firstprev=current;
//seting 2nd previous
while(current->next!=second)
{
current=current->next;
}
// swap datas, assuming the payload is an int:
int tempdata = first->data;
first->data = second->data;
second->data = tempdata;
//swaping next of the nodes
firstprev->next=second;
secprev->next=first;
}
Here is my Merge sort realisation, with O(N*logN) time complexity and constant additional space. Uses C++11
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
typedef pair<ListNode*, ListNode*> PP;
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (head==nullptr)return head;
if (head->next==nullptr) return head;
if (head->next->next==nullptr){
if (head->val<=head->next->val){
return head;
}
else {
ListNode* second=head->next;
second->next=head;
head->next=nullptr;
return second;
}
}else {
PP splitted=split(head);
return merge(sortList(splitted.first),sortList(splitted.second));
}
}
private:
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode * head=new ListNode(0);
ListNode * current=head;
if (l1==nullptr)return l2;
if (l2==nullptr)return l1;
do {
if (l1->val<=l2->val){
current->next=l1;
l1=l1->next;
}else{
current->next=l2;
l2=l2->next;
}
current=current->next;
}while (l1!=nullptr && l2!=nullptr);
if (l1==nullptr)current->next=l2;
else current->next=l1;
return head->next;
}
PP split(ListNode* node){
ListNode* slow=node;
ListNode* fast=node;
ListNode* prev;
while(fast!=nullptr){
if (fast->next!=nullptr){
prev=slow;
slow=slow->next;
fast=fast->next;
}else break;
if(fast->next!=nullptr){
fast=fast->next;
}
else break;
}
prev->next=nullptr;
return {node,slow};
}
};
Use std::list<T>::sort method. Or if you're being precocious, std::forward_list<T>::sort.
Why re-invent the wheel.

Merge Sort Singly Linked List in C++ failing for large input

Update. its working for 65,519 in the FOR LOOP. If i increase it to 65,520, it fails. Completely strange.
This program is not working for large inputs. It is perfect for small inputs. I am getting an exception on Xcode.
Thread 1 : EXC_BAD_ACCESS (code=2, address = 0x7fff5f3fffb8).
Kindly let me know how I can bypass this strange error.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
typedef struct Node * nodePtr;
struct Node{
int data;
nodePtr next;
};
nodePtr globalHead;
void partition(nodePtr head, nodePtr *front, nodePtr *back){
nodePtr fast;
nodePtr slow;
if (head == NULL || head->next == NULL){
*front = head; // &a
*back = NULL; // &b
}else{
slow = head;
fast = head->next;
while(fast != NULL){
fast = fast->next;
if(fast != NULL){
slow = slow->next;
fast = fast->next;
}
}
*front = head; // a
*back = slow->next; // b
slow->next = NULL;
//printList(*front);
//printList(*back);
}
}
nodePtr mergeLists(nodePtr a, nodePtr b){
nodePtr mergedList = NULL;
if (a == NULL){
return b;
}else if (b == NULL){
return a;
}
try {
if (a->data <= b->data){
mergedList = a;
mergedList->next = mergeLists(a->next, b);
}else{
mergedList = b;
mergedList->next = mergeLists(a, b->next);
}
}
catch (int e) {
cout << "Error is . . " << e << endl;
}
return mergedList;
}
void mergeSort(nodePtr *source){
nodePtr head = *source;
nodePtr a = NULL;
nodePtr b = NULL;
if(head == NULL || head->next == NULL){
return;
}
partition(head, &a, &b);
mergeSort(&a);
mergeSort(&b);
*source = mergeLists(a, b);
}
void push(nodePtr *head, int data){
nodePtr newNode = (nodePtr) malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
if ((*head) == NULL){
*head = newNode;
globalHead = *head;
}else{
(*head)->next = newNode;
*head = newNode;
}
}
void printList(nodePtr head){
nodePtr current = head;
while(current != NULL){
printf("%d ",current->data);
current = current->next;
}
printf("\n");
}
// *head = head in the main function,
// it is only there to connect the two and
// not let make the function return anything
// passed by reference
// globalHead points to the start of the linked list
// if you are passing the address over here you have to
// make a double pointer over there in the function
int main(void)
{
nodePtr head = NULL;
// linked list is formed from top to bottom fashion
// push is done in constant time O(1)
long long int i;
//Pushing 200,000 Elements to the Linked List.
for(i=1 ; i<=200000 ; i++) {
push(&head, rand()%200000);
}
printList(globalHead);
mergeSort(&globalHead);
cout << "After Sorting . . \n";
printList(globalHead);
return 0;
}
Using recursion mergeLists() is the issue, it will call itself for every node on the list. Try changing the code so that the code loops and appends nodes to the initially empty mergeList, using a second pointer to node, or optionally a pointer to pointer to node which is initially set to &mergeList. For example, using the name pMerge instead of mergeList:
Node * mergeLists(Node *a, Node *b)
{
Node *pMerge = NULL; // ptr to merged list
Node **ppMerge = &pMerge; // ptr to pMerge or prev->next
if(a == NULL)
return b;
if(b == NULL)
return a;
while(1){
if(a->data <= b->data){ // if a <= b
*ppMerge = a;
a = *(ppMerge = &(a->next));
if(a == NULL){
*ppMerge = b;
break;
}
} else { // b <= a
*ppMerge = b;
b = *(ppMerge = &(b->next));
if(b == NULL){
*ppMerge = a;
break;
}
}
}
return pMerge;
}
Here is example code of a fast method to sort a linked list using an array of pointers to lists aList[], where aList[i] points to a list of size 2 to the power i, that makes use of mergeLists().
#define NUMLISTS 32 // size of aList
Node * mergeSort(NODE *pList)
{
Node * aList[NUMLISTS]; // array of pointers to lists
Node * pNode;
Node * pNext;
int i;
if(pList == NULL) // check for empty list
return NULL;
for(i = 0; i < NUMLISTS; i++) // zero array
aList[i] = NULL;
pNode = pList; // merge nodes into array
while(pNode != NULL){
pNext = pNode->next;
pNode->next = NULL;
for(i = 0; (i < NUMLISTS) && (aList[i] != NULL); i++){
pNode = mergeLists(aList[i], pNode);
aList[i] = NULL;
}
if(i == NUMLISTS)
i--;
aList[i] = pNode;
pNode = pNext;
}
pNode = NULL; // merge array into one list
for(i = 0; i < NUMLISTS; i++)
pNode = mergeLists(aList[i], pNode);
return pNode;
}

Reverse doubly-link list in C++

I've been trying to figure out how to reverse the order of a doubly-linked list, but for some reason, in my function void reverse() runs while loop once and then crashes for some reason. To answer some questions ahead, I'm self-teaching myself with my brothers help. This isn't all of the code, but I have a display() function which prints all nodes chronologically from start_ptr and a switch which activates certain functions like
case 1 : add_end(); break;
case 2 : add_begin(); break;
case 3 : add_index(); break;
case 4 : del_end(); break;
case 5 : del_begin(); break;
case 6 : reverse(); break;
This is the geist of my code:
#include <iostream>
using namespace std;
struct node
{
char name[20];
char profession[20];
int age;
node *nxt;
node *prv;
};
node *start_ptr = NULL;
void pswap (node *pa, node *pb)
{
node temp = *pa;
*pa = *pb;
*pb = temp;
return;
}
void reverse()
{
if(start_ptr==NULL)
{
cout << "Can't do anything" << endl;
}
else if(start_ptr->nxt==NULL)
{
return;
}
else
{
node *current = start_ptr;
node *nextone = start_ptr;
nextone=nextone->nxt->nxt;
current=current->nxt;
start_ptr->prv=start_ptr->nxt;
start_ptr->nxt=NULL;
//nextone=nextone->nxt;
while(nextone->nxt!= NULL)
{
pswap(current->nxt, current->prv);
current=nextone;
nextone=nextone->nxt;
}
start_ptr=nextone;
}
}
Try this:
node *ptr = start_ptr;
while (ptr != NULL) {
node *tmp = ptr->nxt;
ptr->nxt = ptr->prv;
ptr->prv = tmp;
if (tmp == NULL) {
end_ptr = start_ptr;
start_ptr = ptr;
}
ptr = tmp;
}
EDIT: My first implementation, which was correct but not perfect.
Your implementation is pretty complicated. Can you try this instead:
node * reverse(Node * start_ptr)
{
Node *curr = start_ptr;
Node * prev = null;
Node * next = null;
while(curr)
{
next = curr->nxt;
curr->nxt = prev;
curr->prv = next;
prev = curr;
curr = next;
}
return start_ptr=prev;
}
Here is my updated solution:
node * reverse()
{
node *curr = start_ptr;
node * prev = NULL;
node * next = NULL;
while(curr)
{
next = curr->nxt;
curr->nxt = prev;
curr->prv = next;
prev = curr;
curr = next;
}
return start_ptr=prev;
}
The logic was correct. But the issue was that I was accepting in input argument start_ptr. Which means that I was returning the local copy of it. Now it should be working.
You can simplify your reverse() quite a bit. I'd do something like this:
void reverse()
{
if(start_ptr == NULL)
{
cout << "Can't do anything" << endl;
}
else
{
node *curr = start_ptr;
while(curr != NULL)
{
Node *next = curr->next;
curr->next = curr->prev;
curr->prev = next;
curr = next;
}
start_ptr = prev;
}
}
Explanation: The basic idea is simply to visit each Node and swap the links to previous and next. When we move curr to the next Node, we need to store the next node so we still have a pointer to it when we set curr.next to prev.
Simple solution. reverses in less than half a number of total iterations over the list
template<typename E> void DLinkedList<E>::reverse() {
int median = 0;
int listSize = size();
int counter = 0;
if (listSize == 1)
return;
DNode<E>* tempNode = new DNode<E>();
/**
* A temporary node for swapping a node and its reflection node
*/
DNode<E>* dummyNode = new DNode<E>();
DNode<E>* headCursor = head;
DNode<E>* tailCursor = tail;
for (int i = 0; i < listSize / 2; i++) {
cout << i << "\t";
headCursor = headCursor->next;
tailCursor = tailCursor->prev;
DNode<E>* curNode = headCursor;
DNode<E>* reflectionNode = tailCursor;
if (listSize % 2 == 0 && listSize / 2 - 1 == i) {
/**
* insert a dummy node for reflection
* for even sized lists
*/
curNode->next = dummyNode;
dummyNode->prev = curNode;
reflectionNode->prev = dummyNode;
dummyNode->next = reflectionNode;
}
/**
* swap the connections from previous and
* next nodes for current and reflection nodes
*/
curNode->prev->next = curNode->next->prev = reflectionNode;
reflectionNode->prev->next = reflectionNode->next->prev = curNode;
/**
* swapping of the nodes
*/
tempNode->prev = curNode->prev;
tempNode->next = curNode->next;
curNode->next = reflectionNode->next;
curNode->prev = reflectionNode->prev;
reflectionNode->prev = tempNode->prev;
reflectionNode->next = tempNode->next;
if (listSize % 2 == 0 && listSize / 2 - 1 == i) {
/**
* remove a dummy node for reflection
* for even sized lists
*/
reflectionNode->next = curNode;
curNode->prev = reflectionNode;
}
/**
* Reassign the cursors to position over the recently swapped nodes
*/
tailCursor = curNode;
headCursor = reflectionNode;
}
delete tempNode, dummyNode;
}
template<typename E> int DLinkedList<E>::size() {
int count = 0;
DNode<E>* iterator = head;
while (iterator->next != tail) {
count++;
iterator = iterator->next;
}
return count;
}
I suggest maintaining a link to the last node.
If not, find the last node.
Traverse the list using the "previous" links (or in your case, prv).
There is no need to actually change the links around. Traversing using the prv pointer will automatically visit the nodes in reverse order.
Look at
valuesnextone=nextone->nxt->nxt;
Here nextone->nxt can be null.
Apart from that, try to use pointers to pointers in the swap function.
Your pswap function is wrong
your should swap the pointer not try to create temporary objects and swap them.
Should be like that (there might be other mistake later)
void pswap (node *&pa, node *&pb)
{
node* temp = pa;
pa = pb;
pb = temp;
return;
}
A very simple and O(n) solution using two pointers:
start = head of the doubly LL
struct node *temp, *s;
s = start;
while(s != NULL){
temp = s->prev;
s->prev = s->next;
s->next = temp;
s = s->prev;
}
//if list has more than one node
if(current != NULL){
start = temp->prev;
}
My code for reversing doubly linked list,
Node* Reverse(Node* head)
{
// Complete this function
// Do not write the main method.
if(head != NULL) {
Node* curr = head;
Node* lastsetNode = curr;
while(curr != NULL) {
Node* frwdNode = curr->next;
Node* prevNode = curr->prev;
if(curr==head) {
curr->next = NULL;
curr->prev = frwdNode;
lastsetNode = curr;
}
else {
curr->next = lastsetNode;
curr->prev = frwdNode;
lastsetNode = curr;
}
curr = frwdNode;
}
head = lastsetNode;
}
return head;
}
I thought I'd add a recursive solution here.
node* reverse_and_get_new_head(node* head) {
if (head == nullptr) { return nullptr; }
// This can be avoided by ensuring the initial,
// outer call is with a non-empty list
std::swap(head->prev, head->next);
if (head->prev == nullptr) { return head; }
return reverse_and_get_new_head(head->prev);
}
void reverse() {
start_ptr = reverse_and_get_new_head(start_ptr);
}