1. 程式人生 > >C和C指針小記(十八)-使用結構和指針-雙向鏈表

C和C指針小記(十八)-使用結構和指針-雙向鏈表

malloc 雙鏈表 struct 成功 參數 -- 節點 有序 ret

1、雙鏈表

1.1 雙向鏈表的聲明

在一個雙鏈表中,每個節點都包含兩個指針--指向前一個節點的指針和指向後一個節點的指針.

聲明

typedef struct NODE {
    struct NODE *fwd;
    struct NODE *bwd;
    int                value;
} Node;

根節點的fwd字段指向鏈表的第1個節點,根節點的bwd字段指向鏈表的最後一個節點.如果鏈表為空,這兩個字段都為NULL.鏈表的第1個節點的bwd 字段和最後一個節點的 fwd 字段都為 NULL. 在一個有序的鏈表中,各個節點將根據value 字段的值以升序排列.

3.2 雙向鏈表的插入

將一個新值插入到有序表中
函數原型
dll_insert( Node *rootp, int value );
dll_insert 接受兩個參數,一個指向根節點的指針和一個整型值.
插入節點時,可能會遇到4中情況:
1、新值可能必須插入到鏈表的中間位置
2、新值可能必須插入到鏈表的起始位置
3、新值可能必須插入到鏈表的結束位置
4、新值可能必須既插入到鏈表的起始位置,又插入到鏈表的結束位置


/**
 向雙向鏈表中插入數據

 @param rootp 根節點
 @param value 帶插入值
 @return 0 已經有值, -1 不能插入, 1 插入成功
 */
int dll_insert( Dnode *rootp, int value) {
    Dnode   *this;
    Dnode   *next;
    Dnode   *newnode;
    
    //查看 value 是否已經存在於鏈表中, 如果是就返回.否則,為新值創建一個新節點(“newnode”將指向它)
    //this 將指向應該在新節點之前的那個節點
    //next 將指向應該在新節點之後的那個節點
    for( this = rootp; (next = this->fwd) != NULL; this = next){
        if (next->value == value) {
            return 0;
        }
        if (next->value > value) {
            break;
        }
    }
    
    newnode = (Dnode *)malloc( sizeof( Dnode) );
    if ( newnode == NULL) {
        return -1;
    }
    newnode->value = value;
    
    //把新值添加到鏈表中
    if ( next != NULL) {
        //情況 1,2 並非位於鏈表尾部.
        if ( this != rootp ) {//情況1 並非位於鏈表起始位置
            newnode->fwd = next;
            this->fwd = newnode;
            newnode->bwd = this;
            next->bwd = newnode;
        }else {// 情況2 位於起始位置
            newnode->fwd = next;
            this->fwd = newnode;
            newnode->bwd = NULL;
            next->bwd = newnode;
        }
    }else {
        //情況3,4 位於鏈表的尾部
        if (this != rootp) {// 情況3 並非位於鏈表的起始位置
            newnode->fwd = NULL;
            this->fwd = newnode;
            newnode->bwd = this;
            rootp->bwd = newnode;
        }else {// 情況4 位於鏈表起始位置
            newnode->fwd = NULL;
            this->fwd = newnode;
            newnode->bwd = NULL;
            rootp->bwd = newnode;
        }
    }
    
    return 1;
}
//添加節點的4種情況可以提煉
if ( next != NULL) {
        //情況1 或 2 並非位於鏈表的尾部
        newnode->fwd = next;
        if (this != rootp ) {//情況1 並非位於鏈表的起始位置
            this->fwd = newnode;
            newnode->bwd = this;
        }else {//情況2 位於鏈表的起始位置
            rootp->fwd = newnode;
            newnode->bwd = NULL;
        }
        next->bwd = newnode;
    }else {
        //情況3或4 位於鏈表尾部
        newnode->fwd = NULL;
        if (this != rootp) {//情況3 並不位於鏈表起始位置
            this->fwd = newnode;
            newnode->bwd = this;
        }else {//情況4 位於鏈表起始位置
            rootp->fwd = newnode;
            newnode->bwd = NULL;
        }
        rootp->bwd = newnode;
    }

C和C指針小記(十八)-使用結構和指針-雙向鏈表