轉載地址:https://www.2cto.com/kf/201602/490775.html
鏈表在數據結構和算法中的重要性不言而喻。這裏我們要用C來實現鏈表(單鏈表)中的基本操作。對於鏈表的基本概念請參考《數據結構與算法之鏈表》這篇博客。
(1)定義單鏈表的節點類型
1
2
3
4
5
6
7
|
typedef
int
elemType ; //
定義單鏈表結點類型 typedef
struct ListNode{ elemType
element; //數據域 struct
ListNode *next; //地址域 }Node; |
1
2
3
4
5
6
|
//
1.初始化線性表,即置單鏈表的表頭指針爲空 void
initList(Node *pNode){ pNode
= NULL; printf( "%s函數執行,初始化成功\n" ,__FUNCTION__); } |
(3)創建線性表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
//
2.創建線性表,此函數輸入負數終止讀取數據 Node
*creatList(Node *pHead){ Node
*p1; //表頭節點,始終指向頭結點 Node
*p2; //表尾節點,始終指向鏈表的最後一個元素 p1
= p2 = (Node *)malloc(sizeof(Node)); //申請新節點,分配空間 if (p1
== NULL || p2 == NULL){ printf( "內存分配失敗\n" ); exit( 0 ); } memset(p1, 0 ,sizeof(Node)); scanf( "%d" ,&p1->element);
//輸入新節點的值 p1->next
= NULL; //新節點的指針置爲空 while (p1->element
> 0 ){
//輸入的值大於0則繼續,直到輸入的值爲負 if (pHead
== NULL){ //空表,接入表頭 pHead
= p1; //直接把p1作爲頭結點,也可以理解爲把pHead頭結點指向p1 } else { p2->next
= p1; //非空表,接入表尾 } p2
= p1; //p1插入後,p1就是尾結點,所以p2要指向尾結點 p1
= (Node *)malloc(sizeof(Node)); //再重申請一個節點 if (p1
== NULL || p2 == NULL){ printf( "內存分配失敗\n" ); exit( 0 ); } memset(p1, 0 ,sizeof(Node)); scanf( "%d" ,&p1->element); p1->next
= NULL; } printf( "%s函數執行,鏈表創建成功\n" ,__FUNCTION__); return
pHead; //返回鏈表的頭指針 } |
(4)打印鏈表
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//
3.打印鏈表,鏈表的遍歷 void
printList(Node *pHead){ if (NULL
== pHead){ //鏈表爲空 printf( "%s函數執行,鏈表爲空\n" ,__FUNCTION__); } else { while (NULL
!= pHead){ printf( "%d
" ,pHead->element); pHead
= pHead->next; } printf( "\n" ); } } |
(5)清空鏈表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//
4.清除線性表L中的所有元素,即釋放單鏈表L中所有的結點,使之成爲一個空表 void
clearList(Node *pHead){ Node
*pNext; //定義一個與pHead相鄰節點,理解爲當前節點的下一個節點 if (pHead
== NULL){ printf( "%s函數執行,鏈表爲空\n" ,__FUNCTION__); } while (pHead->next
!= NULL){ pNext
= pHead->next; //保存下一結點的指針 free(pHead);
//釋放當前節點 pHead
= pNext; //指向下一個節點 } printf( "%s函數執行,鏈表已經清除\n" ,__FUNCTION__); } |
(6)計算鏈表長度
1
2
3
4
5
6
7
8
9
10
11
12
|
//
5.返回單鏈表的長度 int
sizeList(Node *pHead){ int
size = 0 ; while (pHead
!= NULL){ size++; pHead
= pHead->next; } printf( "%s函數執行,鏈表長度
%d \n" ,__FUNCTION__,size); return
size; //鏈表的實際長度 } |
(7)判斷鏈表是否爲空
1
2
3
4
5
6
7
8
9
10
11
|
//
6.檢查單鏈表是否爲空,若爲空則返回1,否則返回0 int
isEmptyList(Node *pHead){ if (pHead
== NULL){ printf( "%s函數執行,鏈表爲空\n" ,__FUNCTION__); return
1 ; } printf( "%s函數執行,鏈表非空\n" ,__FUNCTION__); return
0 ; } |
(8)查找鏈表某個位置元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
//
7.返回單鏈表中第pos個結點中的元素,若pos超出範圍,則停止程序運行 void
getElement(Node *pHead, int
pos){ int
i = 0 ; if (pos
< 1 ){ printf( "%s函數執行,pos值非法\n" ,__FUNCTION__); } if (pHead
== NULL){ printf( "%s函數執行,鏈表爲空\n" ,__FUNCTION__); } while (pHead
!= NULL){ i++; if (i
== pos){ break ; } pHead
= pHead->next; //移到下一結點 } if (i
< pos){ //pos值超過鏈表長度 printf( "%s函數執行,pos值超出鏈表長度\n" ,__FUNCTION__); } printf( "%s函數執行,位置
%d 中的元素爲 %d\n" ,__FUNCTION__,pos,pHead->element); } |
(9)返回某元素值在鏈表中的內存地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
//
8.從單鏈表中查找具有給定值x的第一個元素,若查找成功則返回該結點data域的存儲地址,否則返回NULL elemType*
getElemAddr(Node *pHead, elemType x){ if (NULL
== pHead){ printf( "%s函數執行,鏈表爲空\n" ,__FUNCTION__); return
NULL; } while ((pHead->element
!= x) && (NULL != pHead->next)) { //判斷是否到鏈表末尾,以及是否存在所要找的元素 pHead
= pHead->next; } if ((pHead->element
!= x) && (pHead != NULL)){ //當到達最後一個節點 printf( "%s函數執行,在鏈表中未找到x值\n" ,__FUNCTION__); return
NULL; } if (pHead->element
== x){ printf( "%s函數執行,元素
%d 的地址爲 0x%x\n" ,__FUNCTION__,x,&(pHead->element)); } return
&(pHead->element); //返回元素的地址 } |
(10)修改某個節點的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
//
9.把單鏈表中第pos個結點的值修改爲x的值,若修改成功返回1,否則返回0 int
modifyElem(Node *pNode, int
pos,elemType x){ int
i = 0 ; if (NULL
== pNode){ printf( "%s函數執行,鏈表爲空\n" ,__FUNCTION__); return
0 ; } if (pos
< 1 ){ printf( "%s函數執行,pos值非法\n" ,__FUNCTION__); return
0 ; } while (pNode
!= NULL){ i++; if (i
== pos){ break ; } pNode
= pNode->next; //移到下一結點 } if (i
< pos) { //pos值大於鏈表長度 printf( "%s函數執行,pos值超出鏈表長度\n" ,__FUNCTION__); return
0 ; } pNode->element
= x; printf( "%s函數執行\n" ,__FUNCTION__); return
1 ; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//
10.向單鏈表的表頭插入一個元素 int
insertHeadList(Node **pNode,elemType insertElem){ Node
*pInsert; pInsert
= (Node *)malloc(sizeof(Node)); memset(pInsert, 0 ,sizeof(Node)); pInsert->element
= insertElem; pInsert->next
= *pNode; *pNode
= pInsert; //頭節點*pNode指向剛插入的節點,注意和上一行代碼的前後順序; printf( "%s函數執行,向表頭插入元素成功\n" ,__FUNCTION__); return
1 ; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//
11.向單鏈表的末尾添加一個元素 int
insertLastList(Node **pNode,elemType insertElem){ Node
*pInsert; Node
*pHead; pHead
= *pNode; pInsert
= (Node *)malloc(sizeof(Node)); //申請一個新節點 memset(pInsert, 0 ,sizeof(Node)); pInsert->element
= insertElem; while (pHead->next
!= NULL){ pHead
= pHead->next; } pHead->next
= pInsert; //將鏈表末尾節點的下一結點指向新添加的節點 printf( "%s函數執行,向表尾插入元素成功\n" ,__FUNCTION__); return
1 ; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
int
main( int
argc, const
char
* argv[]) { Node
*pList; //聲明頭結點 initList(pList);
//鏈表初始化 printList(pList);
//遍歷鏈表,打印鏈表 pList
= creatList(pList); //創建鏈表 printList(pList); sizeList(pList);
//鏈表的長度 printList(pList); isEmptyList(pList);
//判斷鏈表是否爲空鏈表 getElement(pList, 3 );
//獲取第三個元素,如果元素不足3個,則返回0 printList(pList); getElemAddr(pList, 5 );
//獲得元素5的內存地址 modifyElem(pList, 4 , 1 );
//將鏈表中位置4上的元素修改爲1 printList(pList); insertHeadList(&pList, 5 );
//表頭插入元素5 printList(pList); insertLastList(&pList, 10 );
//表尾插入元素10 printList(pList); clearList(pList);
//清空鏈表 printList(pList); return
0 ; } |