banner
darkan

darkan

鏈表

鏈表介紹#

鏈表的定義#

// 單鏈表
struct ListNode {
    int val;  // 節點上存儲的元素
    ListNode *next;  // 指向下一個節點的指針
    ListNode(int x) : val(x), next(NULL) {}  // 節點的構造函數
};

通過自己定義構造函數初始化節點:

ListNode* head = new ListNode(5);

鏈表的刪除和添加#

image.png|450
image.png|450

移除鏈表的元素#

設置一個虛擬頭結點在進行移除節點操作:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummyHead = new ListNode(0); // 設置一個虛擬頭結點
        dummyHead->next = head; // 將虛擬頭結點指向head,這樣方便後面做刪除操作
        ListNode* cur = dummyHead;
        while (cur->next != NULL) {
            if(cur->next->val == val) {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            } else {
                cur = cur->next;
            }
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;
    }
};

設計鏈表#

class MyLinkedList {
public:
    // 定義鏈表節點結構體
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    };

    // 初始化鏈表
    MyLinkedList() {
        _dummyHead = new LinkedNode(0); // 這裡定義的頭結點 是一個虛擬頭結點,而不是真正的鏈表頭結點
        _size = 0;
    }

    // 獲取到第index個節點數值,如果index是非法數值直接返回-1, 注意index是從0開始的,第0個節點就是頭結點
    int get(int index) {
        if (index > (_size - 1) || index < 0) {
            return -1;
        }
        LinkedNode* cur = _dummyHead->next;
        while(index--){ // 如果--index 就會陷入死循環
            cur = cur->next;
        }
        return cur->val;
    }

    // 在鏈表最前面插入一個節點,插入完成後,新插入的節點為鏈表的新的頭結點
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = _dummyHead->next;
        _dummyHead->next = newNode;
        _size++;
    }

    // 在鏈表最後面添加一個節點
    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(cur->next != nullptr){
            cur = cur->next;
        }
        cur->next = newNode;
        _size++;
    }

    // 在第index個節點之前插入一個新節點,例如index為0,那麼新插入的節點為鏈表的新頭節點。
    // 如果index 等於鏈表的長度,則說明是新插入的節點為鏈表的尾結點
    // 如果index大於鏈表的長度,則返回空
    // 如果index小於0,則在頭部插入節點
    void addAtIndex(int index, int val) {

        if(index > _size) return;
        if(index < 0) index = 0;        
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }

    // 刪除第index個節點,如果index 大於等於鏈表的長度,直接return,注意index是從0開始的
    void deleteAtIndex(int index) {
        if (index >= _size || index < 0) {
            return;
        }
        LinkedNode* cur = _dummyHead;
        while(index--) {
            cur = cur ->next;
        }
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        //delete命令指示釋放了tmp指針原本所指的那部分內存,
        //被delete后的指針tmp的值(地址)並非就是NULL,而是隨機值。也就是被delete后,
        //如果不再加上一句tmp=nullptr,tmp會成為亂指的野指針
        //如果之後的程序不小心使用了tmp,會指向難以預想的內存空間
        tmp=nullptr;
        _size--;
    }

    // 打印鏈表
    void printLinkedList() {
        LinkedNode* cur = _dummyHead;
        while (cur->next != nullptr) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }
private:
    int _size;
    LinkedNode* _dummyHead;

};

翻轉鏈表#

雙指針法#

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一個節點
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一個節點,因為接下來要改變cur->next
            cur->next = pre; // 翻轉操作
            // 更新pre 和 cur指針
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

递归法#

class Solution {
public:
    ListNode* reverse(ListNode* pre,ListNode* cur){
        if(cur == NULL) return pre;
        ListNode* temp = cur->next;
        cur->next = pre;
        // 可以和雙指針法的代碼進行對比,如下遞歸的寫法,其實就是做了這兩步
        // pre = cur;
        // cur = temp;
        return reverse(cur,temp);
    }
    ListNode* reverseList(ListNode* head) {
        // 和雙指針法初始化是相同的邏輯
        // ListNode* cur = head;
        // ListNode* pre = NULL;
        return reverse(NULL, head);
    }

};

兩兩交換鏈表中的節點#

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。