1. 程式人生 > 其它 >蘋果 macOS Monterey 12.2 Beta 釋出,重構 Apple Music :效能更強更流暢

蘋果 macOS Monterey 12.2 Beta 釋出,重構 Apple Music :效能更強更流暢

遞迴反轉

本文介紹遞迴反轉單鏈表,和之前的迴圈遍歷反轉單鏈表方式略有不同,遞迴的方式要寫出推到遞迴公式。並且在遞迴的同時修改指標的指向。
先定義Node節點

class Node
{
public:
    Node(int dt, Node *nt = nullptr) : data(dt), next(nt) {}
    Node() = default;
    int data;
    Node *next;
};

Node節點構成的連結串列如下圖

基本思路是實現recursive_reverse函式

Node* recursive_reverse(Node* p){
    //判斷p為空或者是單節點直接返回
    if(p == nullptr || p->next==nullptr){
        return ;
    }

    //遞迴查詢,直到返回隊尾元素作為頭節點
    //否則繼續遞迴處理下一個節點
    auto nextnode = recursive_reverse(p->next);
    return nextnode;
}

上述程式碼最終會將連結串列的尾節點返回。但是我們沒有完成連結串列的逆轉,需要改變連結串列節點Node的next指標。
假設有兩個節點

node1節點為p節點
p->next指向的就是node2節點
p->next->next指向的就是末尾的空指標。
所以當有兩個節點的時候我們可以如下操作完成p和p->next兩個節點指向的修改,也就是node1和node2兩個節點的修改。
我們將p->next->next = p->next 就是將node2的next指向了node1.
我們將p->next = nullptr 就是將node1->next

指向了空地址。所以node1此時變為尾節點。
而之前的遞迴保證了最後返回的是node2節點,此時node2節點就作為頭節點,從而完成了逆轉。
圖解為下圖

這是兩個節點的情況,如果是三個節點呢,那就依次類推,依次完成node3->next指向node2,node2->next指向node1,node1->next指向空地址。
所以n>=2的情況都是和兩個節點類似的,那麼我們補全recursive_reverse函式

Node *recursive_reverse(Node *p)
{
    //如果連結串列為空或者為單節點,直接返回
    if (p == nullptr || p->next == nullptr)
    {
        return p;
    }
    //否則繼續遞迴處理下一個節點
    auto nextnode = recursive_reverse(p->next);
    //改變p的下一個節點next指向,連結串列逆轉
    p->next->next = p;
    //改變p的next指向
    p->next = nullptr;
    return nextnode;
}

接下來我們實現一個建立連結串列的函式用來測試

Node *createList()
{
    auto node1 = new Node(1);
    auto node2 = new Node(2);
    auto node3 = new Node(3);
    node1->next = node2;
    node2->next = node3;
    return node1;
}

然後實現銷燬連結串列回收記憶體的函式

void delocateList(Node *p)
{
    while (p != nullptr)
    {
        auto temp = p;
        p = p->next;
        delete temp;
    }
}

然後實現列印節點的函式

void printList(Node *p)
{
    while (p != nullptr)
    {
        cout << p->data << " -> ";
        p = p->next;
    }

    cout << " nullptr " << endl;
}

最後我們在main函式中測試

    auto list = createList();
    printList(list);
    list = recursive_reverse(list);
    printList(list);
    delocateList(list);

程式輸出如下

1 -> 2 -> 3 ->  nullptr
3 -> 2 -> 1 ->  nullptr

可以看到連結串列被逆轉了。
原始碼連結https://gitee.com/secondtonone1/algorithms
我的公眾號,謝謝關注

重劍無鋒,大巧不工