C語言數(shù)據(jù)結構與算法之單鏈表
基本概念

鏈表的每一個結點中只包含一個指針域
優(yōu)點 : 儲存空間利用高效

舉例來說:
typedef struct student{
int id; //學生編號
char* name; //學生名稱
//指向下一結點的指針
struct Student* pNext;
}Student;
與之相反的是多鏈表

typedef struct student{
int id; //學生編號
char* name; //學生名稱
//指向下一結點的指針
struct Student* pNext;
struct Student* qNext;
}Student;
讀取數(shù)據(jù)元素

獲取第i個結點的數(shù)據(jù)元素
- 聲明一個結點指針p指向鏈表的第一個結點a1,初始化j從1開始
- 當j < i 時,遍歷鏈表,讓p的指針向后移動,不斷指向下一個結點,j 累加 1
- 當鏈表末尾 p 為空時,則說明第 i 個元素不存在;否則查找成功,返回結點 p 的數(shù)據(jù)
?
1.定義數(shù)據(jù)元素
//定義數(shù)據(jù)元素
typedef struct student{
int id;
char* name;
}ElementType;
2.定義順序表結構
typedef struct {
ElementType dates[MAX_SIZE]; //當前順序表中的數(shù)據(jù)集合
int length; //當前順序表中的元素個數(shù)
}SeqList;
3.定義鏈表的結點(包括數(shù)據(jù)域和指針域)
typedef struct Node {
ElementType date; //數(shù)據(jù)域
struct Node* node; //指針域,指向下一個結點
}Node;
4.設置頭結點
我們在定義鏈表時,習慣性的會定義頭結點,以便統(tǒng)一鏈表結點的插入和刪除操作
typedef struct Linklist {
Node* next; //頭指針
int length;
}Linklist;
如果鏈表有頭結點,next就指向頭結點,沒有就指向第一個結點
鏈表的長度初始值為0
插入數(shù)據(jù)元素?
在第i個結點后插入數(shù)據(jù)元素 ?
- 創(chuàng)建一個空節(jié)點,分配內存空間,設置數(shù)據(jù)元素
- 獲取第i個結點,設置新結點的后繼結點為該結點的后繼結點
- 設置第i個結點的后繼結點為該結點
1.創(chuàng)建空節(jié)點并為數(shù)據(jù)域賦值
//創(chuàng)建空節(jié)點并為數(shù)據(jù)賦值
Node* node = (Node*)malloc(sizeof(Node));
node -> date = element;
node -> next = NULL;
2.通過循環(huán)找到要插入的結點
for (int i = 1; currNode && i < pos - 1; i++)
{
currNode = currNode->next;
}
3.將結點插入并對接前面的結點
if (currNode) {
node->next = currNode->next;
currNode->next = node;
linkList->length++;
}

初始化鏈表
void InitLinkList(LinkList* linkList, ElementType* dateArrar, int length)
{
for (int i = 0; i < length; i++) {
InsertLinkList(linkList, i + 1, dateArrar[i]);
}
}
打印鏈表
void PrintLinkList(LinkList* linklist)
{
Node* node = linklist->next;
if (!node)
{
printf("鏈表為空!\n");
linklist->length = 0;
return 0;
}
for (int i = 0; i < linklist->length; i++) {
printf("%d\t%s\t\n", node->date.id, node->date.name);
node = node->next;
}
}
順序表查空
int IsLinkListEmpty(LinkList* linkList) {
return linkList->length == 0 ? TRUE : FALSE;
}
順序表的刪除?
刪除第i個結點及其數(shù)據(jù)元素
- 獲取第i個結點,若該結點不是第一個結點,則獲取第i - 1個結點
- 將第i -1個結點的后綴結點設為第i個結點的后綴結點
- 刪除第i個結點,釋放內存空間,記錄并返回刪除數(shù)據(jù)元素的值

情況1:當刪除的是第一個元素
if (pos == 1)
{
node = linkList->next;
if (node) {
element = node->date;
linkList->next = node->next;
free(node); //釋放被刪除的結點
linkList->length--;
}
return element;
}
情況2:除第一個結點外
- 找到要刪除的結點和他的前綴結點
- 要刪除結點的next 賦值給前綴結點
- 釋放要刪除的結點
Node* preNode; //前綴結點
node = linkList->next;
for (int i = 1; node && i < pos; i++)
{
preNode = node;
node = node->next;
}
if (node)
{
element = node->date;
preNode->next = node->next;
free(node);
linkList->length--;
}
return element;
完整代碼
ElementType DeleteLinkListElement(LinkList* linkList, int pos)
{
ElementType element; //被刪除的元素
element.id = -999; //賦一個不可能的值,來判斷刪除是否成功
Node* node = NULL;
if (pos == 1)
{
node = linkList->next;
if (node) {
element = node->date;
linkList->next = node->next;
free(node); //釋放被刪除的結點
linkList->length--;
}
}
Node* preNode; //前綴結點
node = linkList->next;
for (int i = 1; node && i < pos; i++)
{
preNode = node;
node = node->next;
}
if (node)
{
element = node->date;
preNode->next = node->next;
free(node);
linkList->length--;
}
return element;
}
刪除單鏈表整表
- 聲明結點p 和 q
- 將第一個結點賦值給p
- 循環(huán)將下一個結點賦值給q,釋放p,將q賦值給p

?

void CleatLinkList(LinkList* linkList)
{
Node* node = linkList->next;
Node* nextNode;
while (node) {
nextNode = node->next; //先記錄當前結點的下一個結點,以便釋放當前結點的內存
free(node);
node = nextNode;
}
linkList->next = NULL;
linkList->length = 0;
}
單鏈表VS順序表
?
?
以上就是C語言數(shù)據(jù)結構與算法之單鏈表的詳細內容,更多關于C語言單鏈表的資料請關注腳本之家其它相關文章!
相關文章
C語言數(shù)據(jù)結構中數(shù)制轉換實例代碼
這篇文章主要介紹了C語言數(shù)據(jù)結構中數(shù)制轉換實例代碼的相關資料,需要的朋友可以參考下2017-03-03
C++11運算符重載和向量類重載實例詳解(<<,>>,+,-,*等)
這篇文章主要給大家介紹了關于C++11運算符重載和向量類重載的相關資料,主要包括<<,>>,+,-,*等,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2021-07-07

