使用给定的链接列表在C ++中创建反向链接列表

时间:2011-02-05 16:58:44

标签: c++ linked-list

我在给定链接列表中以相反的顺序创建链接列表时遇到了一些麻烦。

我来自java背景,刚刚开始做一些C ++。

你能看看我的代码,看看有什么问题吗?我猜我只是操纵指针而不是创造任何新东西。

//this is a method of linkedlist class, it creates a reverse linkedlist
//and prints it

void LinkedList::reversedLinkedList()
{
    Node* revHead;

    //check if the regular list is empty
    if(head == NULL)
       return;

    //else start reversing
    Node* current = head;
    while(current != NULL)
    {
        //check if it's the first one being added
        if(revHead == NULL)
           revHead = current;

        else
        {
            //just insert at the beginning
            Node* tempHead = revHead;
            current->next = tempHead;
            revHead = current;
        }
        current = current->next;

     }//end while

     //now print it
     cout << "Reversed LinkedList: " << endl;

     Node* temp = revHead;
     while(temp != NULL)
     {
         cout << temp->firstName << endl;
         cout << temp->lastName << endl;
         cout << endl;

         temp = temp->next;
      }

}//end method

11 个答案:

答案 0 :(得分:46)

更简单的一个:浏览链接列表,保存上一个节点和下一个节点,然后让当前节点指向前一个节点:

void LinkedList::reversedLinkedList()
{
    if(head == NULL) return;

    Node *prev = NULL, *current = NULL, *next = NULL;
    current = head;
    while(current != NULL){
        next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }
    // now let the head point at the last node (prev)
    head = prev;
}

答案 1 :(得分:4)

Node* revHead;
// ...
while(current != NULL)
{
    //check if it's the first one being added
    if(revHead == NULL)

初始化revHead但您使用它。 (我希望你已经清楚revHead是一个用于存储内存地址的局部变量,而不是存在于方法/过程之外的东西)

revHead的存储类是自动的(也就是在本地范围体中)。在C++执行此类声明时,无法保证该值为0

(除非存储类的类型为static,或者变量为global,如果没有提供其他值,它将自动初始化为0。在您的情况下,变量具有存储类型为auto的类,这意味着它在函数中是本地定义的,当声明局部变量而没有指定值时,该值是垃圾。请记住,使用下一个C ++标准C++0x关键字auto具有新含义)。

您的案例中的值是垃圾,导致if失败。请在此处查看更多信息:Link

做一个

Node* revHead = NULL;

请记住,您的代码的其他部分可能也会出现类似的错误。

答案 2 :(得分:2)

另一种方法是首先遍历列表并将所有数据存储在堆栈中,然后创建一个新列表并从堆栈顶部插入数据。堆栈为LIFO将以相反的顺序为您提供数据,因此您将有一个反向清单。

答案 3 :(得分:2)

这只使用两个临时变量来完成。

Node* list::rev(Node *first)
{
    Node *a = first, *b = first->next;
    while(a->next!=NULL)
    {
        b = a->next;
        a->next = a->next->next;
        b->next = first;
        first = b;
    }
    return first;
}

此外,您可以使用递归来完成此操作。

答案 4 :(得分:0)

NODE * ReverseLinkedList(NODE * head){
    if (head == NULL)
        return NULL;

    NODE * previous = NULL;
    while (head != NULL) {
        // Keep next node since we trash the next pointer.
        NODE *next = head->pNext;
        // Switch the next pointer to point backwards.
        head->pNext = previous;
        // Move both pointers forward.
        previous = head;
        head = next;
    }
    return previous;
}

答案 5 :(得分:0)

我不确定,但我认为你想要一个双向链表,其中节点有下一个和前一个节点。使用指向列表的外部指针不起作用。您将没有上一个节点的地址。

如果不使用上面的方法堆栈,这是一个很好的建议。

答案 6 :(得分:0)

以上是链接列表的反向

void LinkList::rev()
{
    if(pFirst == NULL) return;

    ListElem *prev = NULL, *current = NULL, *next = NULL;
    current = pFirst;
    while(current != NULL)
    {
        next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }
    // now let the head point at the last node (prev)
    pFirst = prev;
}

答案 7 :(得分:0)

下面的示例使用递归来反转链表。我在面试时问了这个问题。这已经过测试和运作。 ListElem是节点。

void LinkList::reverse()
{
if(pFirst == NULL) return;
ListElem* current = pFirst;
revCur(NULL, current, NULL);
}

void LinkList::revCur(ListElem *prev, ListElem* current, ListElem* next)
{
 //   ListElem *prev = NULL, *current = NULL, *next = NULL;
 if ( current != NULL )
 {
     next = current->next;
     current->next = prev;
     prev = current;
     current = next;
     pFirst = prev;
     this->revCur(prev,current,next);
    }
}

答案 8 :(得分:0)

  #include <stdint.h>
  /*
      this is a generic (structure agnostic) routine for reversing a singly linked list.
      1st argument is the memory address the structure is located at, and
      2nd argument is the memory address to this particular structure's NEXT member.
  */
  void *rsll(void *struct_address, void *next_address /*(void **)*/)
  {
    uint32_t offset, holder;
    offset = next_address - struct_address;

    void **p = struct_address, *progress = NULL;
    while(p)
    {
      void *b;
      holder = (uint32_t)p;
      holder += offset;
      p = (void**)holder; //&(N->next)
      b = *p; //(N->next)
      *p = progress; //(N->next)
      holder = (uint32_t)p;
      holder -= offset;
      p = (void**)holder; //N
      progress = p;
      p = b;
    }
    return progress;
  }

  #include <stdio.h>
  int
  main()
  {
    struct list_t
    {
      int integer;
      struct list_t *next;
    };
    struct list_t d = {40,NULL},
                  c = {30,&d},
                  b = {23,&c},
                  a = {10,&b};
    struct list_t *list;
    list = &a;
    list = rsll(list,&(list->next));
    while(list)
    {
      printf("%d\n",list->integer);
      list = list->next;
    }
    return 0;
  }

答案 9 :(得分:0)

我使用类为反向链接列表提供完全可执行的解决方案,因为大多数发现的示例仅使用结构:

#include <iostream>
#include <string>

class listElement
{
    std::string data;
    listElement* next;
    listElement* last; //for doubly linked list

    void append(std::string);
    void displayElements();
    void reverseDisplayElements(listElement*);

    listElement* reverseList(listElement*);


public:
    listElement() = default;
    listElement(std::string newElement)
        :data(newElement)
        , next(nullptr)
        , last(this)
    {}
    listElement &operator=(const listElement& other) = default;
    ~listElement();

    void setElement(std::string element){append(element);}
    void getElements();
    void getElementsReverse(listElement* elements);

    listElement* setElementsInReverseOrder(listElement* elements);
};

listElement::~listElement()
{
    //If the end is not reached, call the method again
    if (next != nullptr)
    {
        next->~listElement();
        delete(next);
    }
}

void listElement::getElements()
{
    std::cout << "\nPrint list:" << std::endl;
    displayElements();
}

void listElement::getElementsReverse(listElement *elements)
{
    std::cout << "\nJust print the list in reverse order:" << std::endl;
    reverseDisplayElements(elements);
}

listElement *listElement::setElementsInReverseOrder(listElement *elements)
{
    std::cout << "\n...Reversing elements..." << std::endl;
    return reverseList(elements);
}

void listElement::append(std::string newData)
{
    // Double linked list
    //    last->next = new listElement();
    //    last->next->data = newData;
    //    last->next->next = nullptr;
    //    last = last->next;

// Singly linked list
    //has next the value nullptr?
    //If yes, next pointer
    if (next == nullptr)
    {
        next = new listElement();
        next->data = newData;
        next->next = nullptr;
    }
    //else the method again
    else
        next->append(newData);
}

listElement* listElement::reverseList(listElement* head)
{
    //return if no element in list
    if(head == nullptr)
        return nullptr;

    //initialize temp
    listElement* temp{};

    while(head != nullptr){
        listElement* next = head->next;
        head->next = temp;
        temp = head;
        head = next;
    }
    return temp;
}

void listElement::displayElements()
{
    //cout the first entry
    std::cout << data << std::endl;
    //if the end is not reached, call method next again
    if (next != nullptr)
        next->displayElements();
}

void listElement::reverseDisplayElements(listElement*head)
{
    //recursiv from the last to the list beginning - stop
    listElement *temp = head;

    if(temp != nullptr)
    {
        if(temp->next != nullptr)
        {
            reverseDisplayElements(temp->next);
        }
      std::cout << temp->data << std::endl;
    }
}

int main ()
{
    //Pointer to the Beginning of the list
    listElement* linkedList = new listElement("Element 1");

    //add more elements
    linkedList->setElement("Element 2");
    linkedList->setElement("Element 3");
    linkedList->setElement("Element 4");

    linkedList->getElements();
    linkedList->getElementsReverse(linkedList);
    linkedList->getElements();
    linkedList = linkedList->setElementsInReverseOrder(linkedList);
    linkedList->getElements();

    return 0;
}

我对生产代码的建议是使用

std::list since it is a linked list

std::vector if you need an efficient array implementation

答案 10 :(得分:0)

思路如下:将每个节点移(link)到左边而不是(link)移到右边,但是这里必须考虑特殊的测试用例是代码

void Sll::Myreverse(){ 

 if( length <= 1 )
      return;

 Node *prev = head , head = head->next ,*next_node = nullptr  ;
 tail = prev , prev->next = nullptr  ;

 while( head ){

      next_node = curr->next ;
      curr->next = prev ;

      prev = curr ;
      curr = next_node ;

 }
 head = prev ;
}