線性表的鏈?zhǔn)酱鎯Y(jié)構(gòu)1.1

這篇文章依然介紹線性表的鏈?zhǔn)酱鎯Y(jié)構(gòu)-單鏈表

單鏈表的整表創(chuàng)建

線性表順序存儲結(jié)構(gòu)的創(chuàng)建,其實就是一個數(shù)組的初始化,即聲明一個類型和容量確定的數(shù)組并賦值的過程。單鏈表和線性表順序存儲結(jié)構(gòu)不一樣,它不像單鏈表那樣內(nèi)存地址是連續(xù)的,元素存儲的地址比較分散,可以存儲在內(nèi)存中未被使用的任意位置,它的大小和位置不是預(yù)先分配好的,而是根據(jù)實際需求即時生成,因此單鏈表是一個 動態(tài)表,創(chuàng)建單鏈表的過程就是一個動態(tài)生成鏈表的過程,從 空表 的初始狀態(tài),依次建立各元素結(jié)點(diǎn),并插入鏈表
單鏈表整表創(chuàng)建的過程需要用到我們前面文章中介紹到的 頭插法尾插法
頭插法創(chuàng)建單鏈表
1.聲明一個結(jié)點(diǎn) p 和 計數(shù)器變量 i
2.初始化一個空鏈表 L
3.將 L 頭結(jié)點(diǎn)的指針域指向 NULL,建立一個帶有頭結(jié)點(diǎn)的單鏈表
4.循環(huán):

  • 生成一個新結(jié)點(diǎn)賦值給 p
  • 隨機(jī)生成一個數(shù)字賦值給結(jié)點(diǎn)p的數(shù)據(jù)域 p->data
  • 將 p 插入到頭結(jié)點(diǎn)與前一新結(jié)點(diǎn)之間
    實現(xiàn)代碼如下:
// 定義一個鏈表結(jié)構(gòu)
typedef struct ListNode
{
    int date;              // 鏈表一個結(jié)點(diǎn)的數(shù)據(jù)域
    struct ListNode *next; // 指向下一個結(jié)點(diǎn)的指針域,即存儲的是下一個結(jié)點(diǎn)的內(nèi)存地址
} Node, *ListLink;         // 結(jié)構(gòu)體變量

// 創(chuàng)建一個新鏈表
void CreateListHead(int n) {
    // 使用malloc函數(shù)為鏈表結(jié)構(gòu)動態(tài)分配一塊內(nèi)存空間,分配成功則返回一個指向該鏈表結(jié)構(gòu)的指針,該指針指向該分配內(nèi)存空間的首地址
    // 即 *L 是頭指針
    *L = (ListLink)malloc(sizeof(Node));
    // 將該結(jié)構(gòu)體的next置為NULL,創(chuàng)建一個包含頭結(jié)點(diǎn)的單鏈表
    (*L)->next = NULL;

    // 初始化隨機(jī)數(shù)種子
    srand(time(0));

    // 循環(huán)
    for (int i = 0; i < n; ++i)
    {
        *p = (ListLink)malloc(sizeof(Node));// 生成新結(jié)點(diǎn)
        (*p)->data = rand() % 100 + 1; // 隨機(jī)生成 100 以內(nèi)的數(shù)據(jù),并將數(shù)據(jù)元素賦值給新結(jié)點(diǎn)的數(shù)據(jù)域

        // 執(zhí)行插入操作
        (*p)->next = (*L)->next;
        (*L)->next = p; 
    }
}

尾插法實現(xiàn)單鏈表創(chuàng)建
代碼實現(xiàn)如下:

// 定義一個鏈表結(jié)構(gòu)
typedef struct ListNode
{
    int date;              // 鏈表一個結(jié)點(diǎn)的數(shù)據(jù)域
    struct ListNode *next; // 指向下一個結(jié)點(diǎn)的指針域,即存儲的是下一個結(jié)點(diǎn)的內(nèi)存地址
} Node, *ListLink;         // 結(jié)構(gòu)體變量

void CreateListTail(int n) {
    // 初始化一個空鏈表
    *L = (ListLink)malloc(sizeof(ListNode));
    // 將該結(jié)構(gòu)體的next設(shè)為 NULL 創(chuàng)建一個帶有頭結(jié)點(diǎn)的單鏈表
    (*L)->next = NULL;

    // 定義尾結(jié)點(diǎn)
    ListLink end = NULL;

    // 將頭結(jié)點(diǎn)賦值給尾結(jié)點(diǎn)
    // 在沒有創(chuàng)建其他結(jié)點(diǎn)之前,只有頭結(jié)點(diǎn),這個時候頭結(jié)點(diǎn)就是尾結(jié)點(diǎn),尾結(jié)點(diǎn)就是頭結(jié)點(diǎn)
    end = *L;

    // 初始化隨機(jī)種子
    srand(time(0));
    
    // 循環(huán)
    for (int i = 0; i < n; ++i)
    {
        // 創(chuàng)建新結(jié)點(diǎn)
        *p = (ListLink)malloc(sizeof(ListNode));
        (*p)->next = rand() % 100 + 1; // 隨機(jī)生成 100 以內(nèi)的數(shù)據(jù),并將數(shù)據(jù)元素賦值給新結(jié)點(diǎn)的數(shù)據(jù)域

        // 執(zhí)行插入操作
        end->next = (*p);
        end = (*p);
    }
    end->next = NULL;
}

注意:在循環(huán)結(jié)束后我們要把尾結(jié)點(diǎn)的指針域置為 NULL,置為 NULL 的原因方便以后遍歷時能確認(rèn)其是尾部

單鏈表的整表刪除

單鏈表整表刪除的算法思路如下:
1.聲明兩個結(jié)點(diǎn) p 和 q
2.將鏈表的第一個結(jié)點(diǎn)賦值給 p
3.循環(huán):

  • 將下一個結(jié)點(diǎn)賦值給 q
  • 使用 free 函數(shù)將 p 釋放
  • 將 q 賦值給 p
    代碼實現(xiàn)如下:
// 單鏈表的整表刪除
Status DeleteList(ListLink *L) {
    // 聲明兩個結(jié)點(diǎn) p 和 q
    ListLink p,q;

    //將鏈表的第一個節(jié)點(diǎn)賦值給 p
    p = (*L)->next;

    while(p) {
        // 將下一個結(jié)點(diǎn)賦值給 q
        q = p->next;
        // 使用 free 函數(shù)將 p 釋放
        free(p);
        q=p;
    }

    // 當(dāng) p 為空時跳出循環(huán)

    // 頭結(jié)點(diǎn)指針域為空
    (*L)->next = NULL;
}
總結(jié)

通過上面的介紹我們簡單的對線性表的順序存儲結(jié)構(gòu)和單鏈表做下對比

存儲方式
  • 順序存儲結(jié)構(gòu)用一塊連續(xù)的存儲單元存儲線性表的數(shù)據(jù)元素
  • 單鏈表采用鏈?zhǔn)酱鎯Ψ绞?,用一組任意的存儲單元存放線性表的數(shù)據(jù)元素
時間性能

1.查找

  • 順序存儲結(jié)構(gòu) O(1)
  • 單鏈表 O(n)
    2.插入和刪除
  • 順序存儲結(jié)構(gòu) O(n)
  • 單鏈表在第一次查找到需要操作的元素位置后,插入和刪除操作的時間復(fù)雜度僅為 O(1)
空間性能
  • 順序存儲結(jié)構(gòu)需要預(yù)先分配存儲空間,分大了,浪費(fèi)空間,分小了,容易溢出
  • 單鏈表不需要預(yù)先分配空間,根據(jù)實際需求分配

通過上面的比對,我們可以得到幾點(diǎn)經(jīng)驗性的結(jié)論:

  • 若線性表頻繁的查找,插入和刪除操作比較少,那么我們可以選擇順序存儲結(jié)構(gòu)。若插入和刪除操作頻繁時,可以選擇單鏈表。這些都是線性表不同存儲方式的優(yōu)缺點(diǎn),實際開發(fā)中的數(shù)據(jù)存儲結(jié)構(gòu)肯定更加復(fù)雜我們需要根據(jù)具體的場景選擇適合的數(shù)據(jù)存儲結(jié)構(gòu)
  • 當(dāng)線性表中的元素我們不清楚具體有多少時或者線性表的數(shù)據(jù)元素個數(shù)變化比較大的時候,最好選擇單鏈表結(jié)構(gòu);而對于那些事先就能知道其數(shù)據(jù)元素個數(shù),可以選擇順序存儲結(jié)構(gòu)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容