(3)链表
目錄
下面是關于鏈表的一些知識點:
鏈表的操作:
創建鏈表
遍歷鏈表
判斷鏈表是否為空
求鏈表長度
插入元素
刪除元素
排序鏈表
?
這篇筆記是根據郝斌老師的上課講義整理而得:
前面介紹了連續的存儲結構:數組,今天來介紹鏈表,是用來進行離散的存儲。首先我們來介紹typedef 的使用:
typedef struct Student {int sid;char[20] name;int age;}* pST,ST;ST st; PST ps = &st; ps->sid =99;下面是關于鏈表的一些知識點:
鏈表的定義:n個節點離散分配,彼此通過指針相連,每個節點只有一個前驅節點,只有一個后續節點,?首節點沒有前驅節點,尾節點沒有后續節點。
首節點:第一個存放有效數據的節點。
尾節點:最后一個存放有效數據的節點。
頭結點:沒有存放數據或者鏈表大小的一個節點,首節點前面的一個節點。其數據類型和首節點一樣。主要為了方便對鏈表的操作。
頭指針:指向頭節點的指針變量。
尾指針:指向尾節點的指針變量。
數組和鏈表的比較:
數組連續,操作方便,獲取非常快,長度固定。
鏈表離散,內存利用率小些(存放額外的指針),插入非常快,查找困難一些。長度不定,動態添加容易。
確定一個鏈表需要的幾個參數:
頭指針,有了頭指針我們就可以推算出其他所有的信息。
一個鏈表的節點定義為:
typedefine struct Node {int data;//數據域,可以是非常復雜的數據結構struct Node * pNext;//指針域 }*PNODE,NODE;鏈表的分類
單鏈表:單向的鏈表,指針域只指向后面或者前面
雙鏈表:每一個節點有兩個指針域,分別指向前節點和后節點
循環鏈表:能通過任何一個節點找到其他所有的節點
非循環鏈表:不是循環的鏈表都是非循環鏈表
鏈表的操作:
# include <stdio.h> # include <malloc.h> # include <stdlib.h>typedef struct Node {int data; //數據域struct Node * pNext; //指針域 }NODE, *PNODE; //NODE等價于struct Node PNODE等價于struct Node *</st//函數聲明 PNODE create_list(void); //創建鏈表 void traverse_list(PNODE pHead); //遍歷鏈表 bool is_empty(PNODE pHead); //判斷鏈表是否為空 int length_list(PNODE); //求鏈表長度 bool insert_list(PNODE pHead, int pos, int val); //在pHead所指向鏈表的第pos個節點的前面插入一個新的結點,該節點的值是val, 并且pos的值是從1開始 bool delete_list(PNODE pHead, int pos, int * pVal); //刪除鏈表第pos個節點,并將刪除的結點的值存入pVal所指向的變量中, 并且pos的值是從1開始 void sort_list(PNODE); //對鏈表進行排序創建鏈表
PNODE create_list(void) {int len; //用來存放有效節點的個數int i;int val; //用來臨時存放用戶輸入的結點的值//分配了一個不存放有效數據的頭結點PNODE pHead = (PNODE)malloc(sizeof(NODE));if (NULL == pHead){printf("分配失敗, 程序終止!\n");exit(-1);}PNODE pTail = pHead;pTail->pNext = NULL;printf("請輸入您需要生成的鏈表節點的個數: len = ");scanf("%d", &len);for (i=0; i<len; ++i){printf("請輸入第%d個節點的值: ", i+1);scanf("%d", &val);PNODE pNew = (PNODE)malloc(sizeof(NODE));if (NULL == pNew){printf("分配失敗, 程序終止!\n");exit(-1);}pNew->data = val;pTail->pNext = pNew;pNew->pNext = NULL;pTail = pNew;}return pHead; }遍歷鏈表
void traverse_list(PNODE pHead) {PNODE p = pHead->pNext;while (NULL != p){printf("%d ", p->data);p = p->pNext;}printf("\n");return; }判斷鏈表是否為空
bool is_empty(PNODE pHead) {if (NULL == pHead->pNext)return true;elsereturn false; }求鏈表長度
int length_list(PNODE pHead) {PNODE p = pHead->pNext;int len = 0;while (NULL != p){++len;p = p->pNext;}return len; }插入元素
bool insert_list(PNODE pHead, int pos, int val) {int i = 0;PNODE p = pHead;while (NULL!=p && i<pos-1){p = p->pNext;++i;}if (i>pos-1 || NULL==p)return false;//如果程序能執行到這一行說明p已經指向了第pos-1個結點,但第pos-1個節點是否存在無所謂//分配新的結點PNODE pNew = (PNODE)malloc(sizeof(NODE));if (NULL == pNew){printf("動態分配內存失敗!\n");exit(-1);}pNew->data = val;//將新的結點存入p節點的后面PNODE q = p->pNext;p->pNext = pNew;pNew->pNext = q;return true; }刪除元素
bool delete_list(PNODE pHead, int pos, int * pVal) {int i = 0;PNODE p = pHead;while (NULL!=p->pNext && i<pos-1){p = p->pNext;++i;}if (i>pos-1 || NULL==p->pNext)return false;//如果程序能執行到這一行說明p已經指向了第pos-1個結點,并且第pos個節點是存在的PNODE q = p->pNext; //q指向待刪除的結點*pVal = q->data; //刪除p節點后面的結點p->pNext = p->pNext->pNext;//釋放q所指向的節點所占的內存free(q);q = NULL;return true;}排序鏈表
void sort_list(PNODE pHead) {int i, j, t;int len = length_list(pHead);PNODE p, q;for (i=0,p=pHead->pNext; i<len-1; ++i,p=p->pNext){for (j=i+1,q=p->pNext; j<len; ++j,q=q->pNext){if (p->data > q->data) //類似于數組中的: a[i] > a[j]{t = p->data;//類似于數組中的: t = a[i];p->data = q->data; //類似于數組中的: a[i] = a[j];q->data = t; //類似于數組中的: a[j] = t;}}}return; }?
總結
- 上一篇: 在Ubuntu上安装Keras深度学习框
- 下一篇: 51nod 1091 重叠的线段(贪心)