本博文僅記錄學習使用,您可以在這裏看我的詳細筆記
#include <stdio.h>
#include <stdlib.h>
// typedef struct Node{...}Node;
// 在學習 C 語言的時候,我們直到 struct 後面的 Node 是可以
// 省略的,但是這裏必須加上,因爲在結構體內部定義了後驅尾
// 該結構,這個時候,在運行代碼的時候,最後的末尾的 Node 沒有
// 運行到,會報錯
typedef int ElemType;
typedef int Status;
typedef struct Node
{
ElemType data;
struct Node *next;
}Node;
// 就是把 struct Node * 定義成了新類型 LinkList。
// 這個類型是一個結構體的指針。
typedef struct Node *LinkList;
// 單鏈表的創建(頭插法
//void CreateListHead(LinkList *L,int n)
//{
// // 創建一個新結點 p
// LinkList p;
// int i;
// // 初始化一個空鏈表
// *L = (LinkList)malloc(sizeof(Node));
// // L 的頭結點指針指向 NULL,這是一個帶頭結點的單鏈表
// (*L)->next = NULL;
// for(i=0;i<n;i++)
// {
// p = (LinkList)malloc(sizeof(Node));
// p->data = i;
// p->next = (*L)->next;
// (*L)->next =p;
// }
//}
// 單鏈表的創建(尾插法)
// n 表示插入的個數
void CreateListTail(LinkList *L,int n)
{
LinkList p,r;
int i;
*L = (LinkList)malloc(sizeof(Node));
// r 指向當前鏈表,注意這裏的 L 和頭插法中的 L
// 有區別,這裏的 L 是指的整個鏈表
// r 是 rear(尾部)的縮寫,此時 r 當作尾結點(因爲
// 當前還沒有新插入的結點 p ,所以認爲 r 是頭結點也對)
r = *L;
for(i=0;i<n;i++)
{
p=(LinkList)malloc(sizeof(Node));
p->data = i;
// 此時 r 爲前一個結點,新創建的結點 p
// 被放在 r 後面(尾插)
r->next = p;
// 然後讓 r 變成 p,這樣 r 又可以作爲尾結點
r = p;
}
r->next = NULL;
printf("創建成功\n");
}
// 單鏈表的整表刪除
Status ClearList(LinkList *L)
{
LinkList p,q;
while(p)
{
q = p->next;
free(p);
p=q;
}
(*L)->next = NULL;
printf("刪除成功\n");
return 1;
}
// 單鏈表的讀取
// i 表示要讀取的位置序號
// e 接收讀取值的變量
Status GetElem(LinkList L,int i,ElemType *e)
{
int j=1; // 爲計數器
LinkList p; // 聲明一個額外的結點
p = L->next; // 將 p 指向鏈表的第一個結點
while(p && j<i) // 當 p 不爲空,且搜索到的邏輯序號接近(當下一個就是目標節點)數目標結點的序號停止
{
p = p->next;
++j;
}
if(!p||j>i)
return 0;
*e = p->data;
return 1;
}
// 插入
// i 表示要插入的位置
// e 表示要插入的值
Status ListInsert(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,s;
p = *L; // p 指向鏈表的第一個結點
j=1;
while(p && j<i)
{
p = p->next; // p 不斷去搜索目標結點
++j;
}
if(!p || j<i)
return 0;
s = (LinkList)malloc(sizeof(Node)); // 系統生成 s 作爲被插入的結點
s->data = e; // 給 s 賦值
s->next = p->next;
p->next = s;
return 1;
}
// 刪除
// i 表示要刪除的位置
// e 表示返回的被刪除的值
Status ListDelete(LinkList *L,int i,ElemType *e)
{
int j;
LinkList p,q;
p = *L;
j = 1;
// 通過這個循環我們找到要刪除的元素的位置
while(p->next && j<i)
{
p = p->next;
++j;
}
if(!(p->next) || j>i)
return 0;
q = p->next;
p->next = q->next;
*e = q->data;
// free 用於釋放一個內存地址
free(q);
return 1;
}
// 顯示當前鏈表所有元素
Status showList(LinkList L)
{
LinkList temp;
temp = L->next;
printf("當前鏈表所有元素:");
while(temp)
{
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
main()
{
LinkList L;
int e;
// 創建大小爲 10 的鏈表
int n = 10;
CreateListTail(&L,n);
// 讀取
GetElem(L,5,&e);
printf("讀取到的數值是:%d\n",e);
// 插入
ListInsert(&L,5,e);
// 顯示
showList(L);
// 刪除
ListDelete(&L,5,&e);
printf("刪除的數值是:%d\n",e);
// 顯示
showList(L);
// 整表刪除
ClearList(&L);
// 顯示
showList(L);
}