關於單向鏈表的逆序

本文轉自:http://chaishushan.blog.163.com/blog/static/130192897200911725838630/

 

假設鏈表的結構爲:

struct Node { int item; Node* next; };


單向鏈表是一個有序的序列.假設有一個單向鏈表A:

1, 2, 3, 4, 5, ...

現在將A表逆序後得到鏈表B:

..., 5, 4, 3, 2, 1


// 常規的反轉鏈表方法

Node *reverse(Node *list)
{
    link t, y = list, r = 0;
    while (y != 0) { t = y->next; y->next = r; r = y; y = t; }    
    return r;
}

其實上面的這個操作自然地對應於棧的出棧/壓棧操作.

因此, 單向鏈表的逆序問題我們也可以抽象爲A和B兩個

棧的轉換問題.


現在給Node實現用於棧的操作函數:

// 1. 判斷棧是否爲空

bool isEmpty(Node* stack)
{
    return (stack == NULL);
}

// 2. 向棧stack中壓入一個node元素

void push(Node* &stack, Node* node)
{
    node->next = stack;
    stack = node;
}

// 3. 從棧stack中彈出一個元素

Node* pop(Node* &stack)
{
    assert(!isEmpty(stack));
    
    Node *t = stack;
    stack = stack->next;
    
    return t;
}

下面可以基於棧實現單向鏈表的逆序操作了.

Node *reverse(Node *oldList)
{
    Node *newList = NULL;
    
    while(!isEmpty(oldList))
    {
        push(newList, pop(oldList));
    }
    
    return newList;
}

採用棧的思維來思考單向鏈表的逆序問題之後,許多本來

相對複雜的問題都會變得異常簡單. 例如, 我們現在再

考慮用遞歸的方法來逆序鏈表.


// 遞歸實現反轉鏈表

Node *reverse(Node *oldList, Node *newList=NULL)
{
    // 判斷oldList是否爲空
    
    if(isEmpty(oldList)) return newList;
    
    // 從oldList棧彈出一個元素
    // 然後將彈出的元素壓到newList棧中
    
    push(newList, pop(oldList));
    
    // 遞歸處理剩下的oldList鏈表
    
    return reverse(oldList, newList);
}

// 遞歸版本的調用方式

int main()
{
    Node *list = NULL;
    
    // newList採用默認的NULL
    
    Node *t = reverse(list);
    
    // ...
}

 

 

 

 

另一種遞歸方法:

 node* reverse( node* pNode, node*& head)
    {
        if ( (pNode == NULL) || (pNode->next == NULL) ) // 遞歸跳出條件
        {
            head = pNode; // 將鏈表切斷,否則會形成迴環
            return pNode;
        }

        node* temp = reserve(pNode->next, head);// 遞歸
        temp->next = pNode;// 將下一節點置爲當前節點,既前置節點
        return pNode;// 返回當前節點
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章