一、鏈表
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、測試結果: