1. 程式人生 > >資料結構之連結串列操作

資料結構之連結串列操作

之前看資料結構時,以為連結串列操作很容易,真正寫程式碼時才發現被打臉了。。。經歷了各種錯誤後,現在總結一下走過的彎路。
這裡主要說下連結串列的增加刪除節點操作。

typedef struct lnode
{
    int data;
    struct lnode *next;
}lnode,*llist;

以上是我定義的節點結構,比較簡單,不再贅述。
下面說下犯的錯誤
錯誤1. addnode函式為增加節點操作

void addnode(lnode *lst,int value)
{
    lnode *p=new lnode();
    p->data=value;
    p->
next=NULL; if (lst==NULL) { lst=p; return; } lnode *q=lst; while (q->next) { q=q->next; } q->next=p; }

好吧,上面屬於低階錯誤,但是一遇到指標就有些搞不清楚。所以這裡想總結一下。
lst為存放lnode結構體地址的指標,初始值為空,在addnode函式體內,對lst賦值,lst改變,但是出了函式,lst仍然為原來值,這是典型的值傳遞(lst內容即地址的值傳遞),行參的改變不影響實參。如果是基本變數,沒有搞錯過,but加了個指標就搞混了。。所以為了改變實參,這裡採用了指標傳遞。
錯誤2.

void addnode(llist *lst,int value)
{
    lnode *p=new lnode();
    p->data=value;
    p->next=NULL;
    if (lst==NULL) {
        *lst=p;
        return;
    }
    lnode *q=*lst;
    while (q->next) {
        q=q->next;
    }
    q->next=p;
}

對待二維指標,一定要認真搞清楚哪個變數指向什麼
這裡寫圖片描述
lst結構如圖所示,lst是地址,地址中存放的內容*lst為p的地址,p中存放的內容*p為lnode的地址。
錯誤2就在於沒有搞清lst=null和*lst=null的區別。
lst=null也就是lst指向0x0000000000000000地址(核心地址,不能訪問),此時,可以對lst另賦值,讓lst指向其他地址,但是不能改變*lst 。
所以,正確的做法應該是判斷*lst是否為null,此時lst為自己的地址,*lst記憶體放的是p的地址,若*lst為null,則說明p為空,即沒有指標指向連結串列,即連結串列為空。
經歷了以上兩次錯誤,最終得到正確答案,在進行插入操作時,要注意連結串列為空的情況;刪除時,也需要注意刪除第一個節點的情況。
正確程式碼:

void addnode(llist *lst,int value)
{
    lnode *p=new lnode();
    p->data=value;
    p->next=NULL;
    if (*lst==NULL) {
        *lst=p;
        return;
    }
    lnode *q=*lst;
    while (q->next) {
        q=q->next;
    }
    q->next=p;
}
void deletenode(llist *p,int value)
{
    if (p==NULL||(*p)==NULL) {
        return;
    }
    else
    {
        lnode *q=*p;
        lnode *r=q;
        if (q->data==value) {
            *p=q->next;
            delete q;
            q=NULL;
            return;
        }
        while (q->next && q->data!=value) {
            r=q;
            q=q->next;
        }
        if (q->data==value) {//判斷最後一個節點是否為value
            r->next=q->next;
            delete q;
            q=NULL;
        }
    }
}