在C ++中反向双向链表

时间:2010-07-07 20:35:56

标签: c++ linked-list reverse

我一直试图弄清楚如何颠倒双向链表的顺序,但由于某种原因,在我的函数void reverse()中运行while循环一次然后由于某种原因崩溃。为了回答一些问题,我在兄弟的帮助下自我教学。这不是所有的代码,但我有一个display()函数,它按时间顺序打印start_ptr的所有节点和一个激活某些函数的开关,如

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

10 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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中接受了。这意味着我正在返回它的本地副本。现在应该可以了。

答案 2 :(得分: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时仍然指向它。

答案 3 :(得分: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;
}

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

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

无需实际更改链接。使用prv指针遍历将自动以相反的顺序访问节点。

答案 6 :(得分:0)

看看

valuesnextone=nextone->nxt->nxt;

此处nextone->nxt可以为空。

除此之外,尝试在交换函数中使用指针指针。

答案 7 :(得分:0)

使用两个指针的非常简单的O(n)解决方案:

start =双重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;
}

答案 8 :(得分: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;
}

答案 9 :(得分:0)

我想在这里添加一个递归解决方案。

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