1. 程式人生 > >經典演算法學習——逆轉連結串列

經典演算法學習——逆轉連結串列

       連結串列在資料結構中是一種非常重要的線性資料結構,也是各類面試筆試中常常涉及的問題。其中最常見的一個問題就是“輸入一個連結串列的頭結點,從尾到頭反過來打印出每個節點的值”,簡單說就是逆轉連結串列。當然,有人會發現,這其實就是劍指Offer中的一道題。這道題的實現我已經上傳至  https://github.com/chenyufeng1991/ReverseLinkedList_Stack

      這道題最經典的實現就是使用棧。在我們正向遍歷連結串列的每個節點的時候,分別把每一個節點入棧,等到所有節點入棧後,再從棧頂彈出每一個節點,此時彈出的節點順序就是連結串列從尾到頭的順序。而棧結構在C++中使用STL是很容易實現的,程式碼如下:

/**
 *  輸入一個連結串列的頭結點,從尾到頭列印連結串列的每一個節點
 */
#include <iostream>
#include <stdlib.h>
#include <stack>

using namespace std;

typedef struct ListNode{
    int element;
    struct ListNode *next;
}Node;

void CreateLinkedList(Node **head);
void ReverseLinkedList(Node *pNode);

int main(int argc, const char * argv[])
{
    Node *pList;
    CreateLinkedList(&pList);
    ReverseLinkedList(pList);

    return 0;
}

/**
 *  指標是指向一個變數在記憶體中的地址;
 *  指標的指標是指向一個指標在記憶體中的地址;
 */
void CreateLinkedList(Node **head)
{
    cout<<"依次輸入數字建立連結串列,輸入<=0建立結束"<<endl;
    *head = (Node *)malloc(sizeof(Node));
    memset(*head, 0, sizeof(int));
    (*head)->next = NULL;

    Node *pInsert;
    Node *pMove;
    pInsert = (Node *)malloc(sizeof(Node));
    memset(pInsert, 0, sizeof(Node));
    pInsert->next = NULL;

    cin>>pInsert->element;
    pMove = *head;
    while (pInsert->element > 0)
    {
        pMove->next = pInsert;
        pMove = pInsert;

        pInsert = (Node *)malloc(sizeof(Node));
        memset(pInsert, 0, sizeof(Node));
        pInsert->next = NULL;

        cin>>pInsert->element;
    }
}

void ReverseLinkedList(Node *pNode)
{
    stack<Node *> nodes;

    // 要入棧的節點是真正連結串列的第一個結點,而不是頭結點
    pNode = pNode->next;
    while (pNode != NULL)
    {
        nodes.push(pNode);
        pNode = pNode->next;
    }

    while (!nodes.empty())
    {
        Node *top = nodes.top();
        cout<<top->element<<" ";
        nodes.pop();
    }
}

     除上面的思路以外,還有一種辦法來實現:在遍歷當前連結串列的時候,取出該節點,用頭插法建立一個新連結串列,新連結串列就是原連結串列的逆序。這種實現可以參考我的另一篇部落格 C語言實現單鏈表的逆序列印(帶頭結點)  。