2010-07-07 79 views
2

我一直在想如何颠倒双向链表的顺序,但由于某种原因,在我的函数void reverse()运行while循环一次,然后由于某种原因崩溃。为了回答一些问题,我在兄弟们的帮助下自我教导自己。这还不是全部的代码,但我有一个display()功能,按时间顺序打印所有节点从start_ptr和激活像C++中的反向双链表

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; 

某些功能的开关这是我的代码的感性:

#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; 
    } 
} 
+2

您正在交换节点的内容而不仅仅是节点p ointers。你确定要这么做吗? – 2010-07-07 20:43:12

+0

在相关说明中,您可以从不同的角度来看待事物。而不是颠倒双链表本身的内容,而是可以专注于反向列表中的内容,这应该是直接的,因为列表是双向链接的。例如,为您的列表实现STL样式的双向迭代器。它们可以与'std :: reverse_iterator <>'适配器一起使用(对于'rbegin()'和'rend()')。一旦实现了这些方法,使用STL算法就会很简单,包括'std :: reverse()'。这是一个有趣的练习,海事组织。 – Void 2010-07-07 23:42:51

回答

6

试试这个:

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; 
} 
+0

最好的一个,虽然我有一个大脑放屁,因为你没有结束与NULL – danutenshu 2010-07-07 21:32:17

+0

指针列表哇,谢谢很多人,我固定你的代码了一下,它看起来比我所有的更漂亮其他尝试。你所要做的就是在'start_ptr == NULL ||时添加一个限定条件start_ptr-> nxt == NULL'并且让你的代码的一部分成为其他的结尾。在那里面,我确信在最后的代码中,'end_ptr-> nxt = NULL;'感谢一大堆 – danutenshu 2010-07-07 21:35:42

+0

我不确定你为什么需要这些检查 - 我认为我给出的代码在没有它们的情况下工作得很好。最后,end_ptr-> nxt将为NULL,因为在开始时,start_ptr-> prv为NULL。不过,无论如何,不​​客气。 – Borealid 2010-07-07 21:48:21

2

您可以简化reverse()不少。我会做这样的事情:

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;  
    } 
} 

说明:基本的想法很简单,就是访问每个Node和交换链接previousnext。当我们将curr移动到下一个Node时,我们需要存储下一个节点,所以当我们将curr.next设置为prev时,我们仍然有一个指向它的指针。

+0

我想你错过了将第一个节点的prev更新为第二个节点。 – Borealid 2010-07-07 20:44:06

+0

事实上,我一开始就一个接一个。现在应该会更好。 – 2010-07-07 20:50:55

3

编辑:我的第一个实现,这是正确的,但不完美。 你的实现非常复杂。你可以试试这个:

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; 
} 

这是我更新的解决方案:

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; 
} 

的逻辑是正确的。但问题是我接受了输入参数start_ptr。这意味着我正在返回它的本地副本。现在它应该工作。

+0

不工作,并创建循环链表 – danutenshu 2010-07-07 21:10:36

+0

我只是无法弄清楚我可能如何做到这一点。 任何人都可以确认这个实现是否创建一个循环链表? 谢谢... – bits 2010-07-07 21:27:41

+0

我试过了,它重复了。 (例如2nd,1st,2nd,1st等) – danutenshu 2010-07-07 21:37:06

0

你的pswap函数是错误的 你应该交换指针而不是尝试创建临时对象并交换它们。 应该是这样的(可能有其他错误后)

void pswap (node *&pa, node *&pb) 
{ 
    node* temp = pa; 
    pa = pb; 
    pb = temp; 
    return; 
} 
+0

这实际上不会做任何事情。您需要将指针传递给指针或引用指针,以便更改应用于原始对象,而不是本地副本。 – SoapBox 2010-07-07 20:53:05

+0

你是绝对正确的,我没有看签名功能。只是修复了临时对象创建错误 – mb14 2010-07-07 20:59:03

0

我建议保持一个链接到最后一个节点。
如果没有,找到最后一个节点。 使用“以前的”链接遍历列表(或者在你的情况下,prv)。

没有必要实际改变周围的链接。使用prv指针遍历将自动以相反的顺序访问节点。

0

valuesnextone=nextone->nxt->nxt; 

这里nextone->nxt可以为空。

除此之外,尝试使用交换功能指针指针。

1

简单的解决方案。逆转小于一半以上的列表

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; 
} 
0

A中的数的总迭代的非常简单的,并使用两个指针O(n)的溶液:

开始=的双重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; 
} 
0

我的代码用于反转双向链表,

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; 
}