單鏈表創(chuàng)建之--頭插法創(chuàng)建帶頭結(jié)點(diǎn)的單鏈表,超詳細(xì)

單鏈表常見的創(chuàng)建方法有頭插法尾插法,這里記錄頭插法創(chuàng)建帶頭結(jié)點(diǎn)的單鏈表具體過程:
以C語言為例,
1)首先使用 typedef 關(guān)鍵字定義結(jié)點(diǎn)數(shù)據(jù)類型

1 typedef struct LNode{
2    int var; //數(shù)據(jù)以整型為例
3    struct LNode* next; //需要定義一個(gè)LNode結(jié)構(gòu)體指針即結(jié)點(diǎn)指針來指向后繼
4 }LNode, *LinkList; 

4行的 LNode 和 *LinkList 可有可無,有的話后面定義結(jié)點(diǎn)變量和指針變量時(shí)更方便,不必須在LNode前面加 struct 關(guān)鍵字,可直接這樣定義變量,

LNode l1, l2; //定義結(jié)點(diǎn)變量
LinkList p1, p2; //定義指針變量

與上面 typedef 關(guān)鍵字定義的單鏈表數(shù)據(jù)類型一樣的定義方法:

struct LNode{
    int var;
    struct LNode* next;
}

若用這種方法定義鏈表結(jié)點(diǎn)類型,定義結(jié)點(diǎn)變量和指針變量時(shí)必須在LNode前帶上struct關(guān)鍵字,即:

struct LNode l1, l2; //定義結(jié)點(diǎn)變量
struct LNode *p1, *p2; //定義指針變量

這兩種定義方法效果是一樣的,都是定義了包含 1個(gè)整型變量的數(shù)據(jù)域1個(gè)后繼指針域的單鏈表結(jié)點(diǎn)類型

2)通過函數(shù) 頭插構(gòu)建鏈表,并返回 LinkList 類型表頭指針變量 L,
算法基本思想:帶有頭結(jié)點(diǎn)的單鏈表有兩類結(jié)點(diǎn),頭結(jié)點(diǎn)元素結(jié)點(diǎn),頭結(jié)點(diǎn)通常不存儲(chǔ)數(shù)據(jù),用L表示,元素結(jié)點(diǎn)存儲(chǔ)數(shù)據(jù),用s表示

2.1 定義頭結(jié)點(diǎn)指針變量L和元素結(jié)點(diǎn)s

LinkList s, L;

2.2 定義了頭結(jié)點(diǎn)之后,內(nèi)存中尚未分配空間,此時(shí)頭結(jié)點(diǎn)并不真實(shí)存在,需使用malloc關(guān)鍵字分配存儲(chǔ)空間后,并使L指針指之,才真正創(chuàng)建了L頭結(jié)點(diǎn)。由于此時(shí)僅有頭結(jié)點(diǎn),無后繼結(jié)點(diǎn),需將其指針域置空

L = (LinkList)malloc(sizeof(LNode)); 
L->next = NULL;
初始化頭結(jié)點(diǎn)

這時(shí)設(shè)置一個(gè)整型變量x,通過不斷輸入其值,來初始化各結(jié)點(diǎn)數(shù)據(jù)域val,判斷x=9999時(shí)為輸入結(jié)束條件,先任意輸入一個(gè)x,然后通過while循環(huán)來判斷 x值決定是否進(jìn)入添加結(jié)點(diǎn)過程

int x;
scanf("%d", &x);
while(x != 9999){ //進(jìn)入添加結(jié)點(diǎn)過程
    ... //不斷添加結(jié)點(diǎn)過程
}

添加結(jié)點(diǎn)過程算法如下:
1, 初始化一個(gè)s元素結(jié)點(diǎn),先初始化數(shù)據(jù)域var,然后初始化指針域next

s = (LinkList)malloc(sizeof(LNode));
s->var = x;
s->next = L->next;

先初始化數(shù)據(jù)域var,然后初始化指針域next頭插法是這樣插入新結(jié)點(diǎn)的,新的結(jié)點(diǎn)s始終在當(dāng)前的表中第一個(gè)元素結(jié)點(diǎn)之前
,也就是L->next 之前插入,數(shù)據(jù)輸入順序與最終鏈表結(jié)點(diǎn)順序是相反的,
所以在創(chuàng)建了一個(gè)新的元素結(jié)點(diǎn)s后,需要將其指針域置為L->next, 如圖

第一個(gè)待插入的元素結(jié)點(diǎn)s初始化后

2, 初始化了一個(gè)元素結(jié)點(diǎn)s后,此時(shí)元素結(jié)點(diǎn)了,由于頭結(jié)點(diǎn)L始終必須作為首個(gè)元素結(jié)點(diǎn)的前驅(qū),所以需要頭結(jié)點(diǎn)L的指針域,使當(dāng)前元素結(jié)點(diǎn)s成為其后繼

L->next = s;

頭結(jié)點(diǎn)L指針域指向元素結(jié)點(diǎn)s

3, 這時(shí),一個(gè)元素結(jié)點(diǎn)s就正式被插入到表中了,然后要插入第二個(gè)元素結(jié)點(diǎn)了,根據(jù)while循環(huán)的流程,再次判斷x值需要再次輸入一個(gè)x值,所以需要在while循環(huán)內(nèi)最后一行輸入x數(shù)據(jù)

scanf("%d", &x);

4,若輸入的值非9999,則再次進(jìn)入while循環(huán),反復(fù)執(zhí)行上述流程,不斷插入元素結(jié)點(diǎn)擴(kuò)大單鏈表長,這里贅述再添加一個(gè)元素結(jié)點(diǎn)的過程
又初始化了一個(gè)元素結(jié)點(diǎn)s,狀態(tài)如圖:

又初始化1個(gè)新的元素結(jié)點(diǎn)s

按照上述算法,頭插法 新的元素結(jié)點(diǎn)s插入時(shí)始終插入在當(dāng)前表中首個(gè)元素結(jié)點(diǎn)F之前,故需要將其后繼指針域置為當(dāng)前表中首個(gè)元素結(jié)點(diǎn)F,即s->next = L->next, 記住L->next始終指向首個(gè)元素結(jié)點(diǎn),結(jié)果如圖:

s被“半插入”到表中

元素結(jié)點(diǎn)s被“半插入”到表中后,F已經(jīng)不是絕對(duì)意義上的首個(gè)元素結(jié)點(diǎn)了,此時(shí)需要更改頭結(jié)點(diǎn)L的后繼指針域,將其后繼指針域置為被“半插入”表中的新元素結(jié)點(diǎn)s,這樣,新的元素結(jié)點(diǎn)s正式被插入表中,表長+1,如圖

插入新元素結(jié)點(diǎn)s

2.3 上述插入過程的函數(shù)完整實(shí)現(xiàn):

LinkList head_Insert(){
    int x;
    LinkList s, L; 
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    scanf("%d", &x);
    while(x != 9999){
        s = (LinkList)malloc(sizeof(LNode));
        s->var = x;
        s->next = L->next;
        L->next = s;
        scanf("%d", &x);
    }
    return L;
}
  1. printList()函數(shù)遍歷打印單鏈表,接收的形參為要打印的單鏈表,從首個(gè)結(jié)點(diǎn)開始打印
void printList(LinkList L){
    while(L != NULL){  
        printf("%d ", L->var);
        L = L->next; //向后遍歷
    } 
}

4)主函數(shù)main() 流程
需要初始化一個(gè)head 指針變量,來接收head_Insert()函數(shù)所返回的已創(chuàng)建的鏈表頭結(jié)點(diǎn)指針值, 然后將head傳入printList()函數(shù)直接調(diào)用打印輸入單鏈表數(shù)據(jù),由于printList()是從首個(gè)結(jié)點(diǎn)開始打印,而頭結(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù),故傳入第一個(gè)元素結(jié)點(diǎn)

int main(){
    LinkList head;
    head = head_Insert();
    printf("the linklist vars are: \n");
    printList(head->next); //由于printList()是從首個(gè)結(jié)點(diǎn)開始打印,而頭結(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù),故傳入第一個(gè)元素結(jié)點(diǎn)
    return 0;
}

程序最終運(yùn)行結(jié)果如圖,可以看到,頭插法建立的單鏈表數(shù)據(jù)順序與輸入順序相反:


程序運(yùn)行結(jié)果
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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