數據結構手把手教學——單向鏈表

一、鏈表

1、鏈表和線性表的關係:鏈表是線性表的鏈式存儲結構
2、鏈表給每塊數據單獨的存儲空間,即存儲空間地址可不連續。

鏈表結構
3、結點類型

struct node{
	datatype data;
	struct node *next;
};

二、單向鏈表

單向鏈表
1、頭結點不存儲數據,且爲空。
2、引入頭結點的原因:在表頭插入、表尾插入或者表中間插入都一樣,讓操作統一、簡化。


三、用C語言實現單向鏈表

1、構造存儲結構

typedef int datatype;
typedef struct linklist
{
    datatype data;  /* 數據域 */
    struct linklist *next;  /* 指針域 */
}link_list, *link_plist;

2、初始化

初始化主要的工作:①申請頭結點空間;②建立空鏈表(head->next=NULL

初始化

/* 初始化 */
void init_linklist(link_plist *list)
{
    *list = (link_plist)malloc(sizeof(link_list));
    if(NULL == *list)
    {
        printf("內存申請失敗\n");
        perror("malloc");   /* 打印內存申請失敗原因 */
        exit(1);
    }
    (*list)->next = NULL;   /* 將next設爲NULL,建立空鏈表 */
}

3、插入

插入主要工作:
第一步:把③的地址放到new->next,即new->next = head->next
第二步:把①的next指向②(new),即head->next = new

鏈表插入結點

/* 插入 */
void insert_linklist(link_plist head, link_plist new)
{
    new->next = head->next;
    head->next = new;
}

4、刪除

刪除主要工作:
第一步:將pnode->next連接到dnode->next
第二步:釋放dnode

鏈表刪除結點

/* 刪除 */
void delete_linklist(link_plist pnode)
{
    link_plist dnode;

    dnode = pnode->next;	/* 沒刪除之前dnode的地址是pnode->next */
    pnode->next = dnode->next;
    free(dnode);
}

5、判斷鏈表是否爲空

判斷鏈表是否爲空只需判斷head->next是否爲NULL即可。

/* 判斷是否爲空 */
bool isempty(link_plist head)
{
    if(NULL == head->next)
    {
        return true;
    }
    else
    {
        return false;
    } 
}

四、練習題

用單向鏈表實現數據逆轉,首先建立一個包含若干整數的單向鏈表,然後參考講義的例子實現數據的逆轉。(比如說把1,2,3,4,5逆轉成5,4,3,2,1)。

1、逆轉思路

①、linklist p, t;p用於指向下一個結點,t用於臨時保存結點數據。

②、讓p = head->next;,也就是一開始讓爲頭結點的下一個結點,也就是第一個保存數據的結點,這裏也就是保持數據1的結點,如下圖所示。
逆轉思路
③、讓head->next = NULL;,也就是讓頭結點與其它結點斷開,如下圖所示:

逆轉思路
④、用t來保存p結點的數據(t = p;),也就是此時t已經保存了第1個結點的數據,然後讓p指向下一個結點p = p->next;p已經來到了第2個結點,接着再將t插入到鏈表,也就插入第1個結點,因爲前面head->next = NULL;,因此插入後如下圖所示:
逆轉思路
⑤、現在p結點時是指向第二個結點,再讓t = p; ,p = p->next;,也就是t已經保存第2個結點的數據了,p已經指向第3個結點了,如下圖所示:
逆轉思路
⑥、現在讓t插入到鏈表中,根據我們前面講的鏈表插入,t是插入到head與第一個結點直接的,如下圖所示:

逆轉思路
⑦、因此,插入後鏈表就變成如下圖所示:
逆轉思路
⑧、按照這個思路下去,最終就能完成逆轉了,如下圖所示:
逆轉思路

⑨、逆轉的代碼如下:

link_plist p = NULL;
link_plist t = NULL;

p = head->next;
head->next = NULL;
    
while(p != NULL)
{
    t = p;
    p = p->next;
    insert_linklist(head, t);
}
2、創建單向鏈表
/* 創建單向鏈表 */
void create_linklist(link_plist head)
{
    link_plist new = NULL;
    link_plist p = head;
    int len = 0;
    int i = 0;

    printf("輸入要插入數據的個數:");
    scanf("%d", &len);

    for(i = 0; i < len; i++)
    {
        new = (link_plist)malloc(sizeof(link_list));
        if(NULL == new)
        {
            printf("內存申請失敗\n");
            perror("malloc");
            exit(1);
        }
        printf("輸入要插入的第%d個數據:", (i+1));
        scanf("%d", &(new->data));
        insert_linklist(p, new);
        p = p->next;

        show_linklist(head);   /* 打印 */
    }
}
3、逆轉數據
/* 將數據逆轉 */
void sort_linklist(link_plist head)
{
    link_plist p = NULL;
    link_plist t = NULL;

    p = head->next;
    head->next = NULL;
    
    while(p != NULL)
    {
        t = p;
        p = p->next;
        insert_linklist(head, t);	/* 這裏實現的是在head後面插入結點,看不明白可看前面插入思路 */
        show_linklist(head);
    }
}

4、主函數main.c
int main(void)
{
    link_plist head;        /* 定義一個頭指針 */

    init_linklist(&head);   /* 初始化 */
    create_linklist(head);  /* 創建單向鏈表 */
    sort_linklist(head);    /* 逆轉 */

    return 0;
}

5、測試結果:
測試結果

五、完整代碼

https://github.com/sanjaywu/DataStructure

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章