一、實驗目的和要求
目的:
- 熟悉單鏈表的創建,取值,查找,插入,刪除等操作。
要求:
- 初始化單鏈表La
- 在La中插入一個新結點
- 刪除La中某個結點
二、實驗內容
(1)單鏈表中插入結點
插入結點有兩種方法,一種頭插,一種尾插
頭插法:從空表開始,重複讀入數據,生成新結點,將讀入的數據存放到新結點的數據域中,然後將新結點插入到當前鏈表的頭結點之後,直至讀入結束標誌爲止,頭插法創建鏈表的根本在於最後兩條語句:
node->next = head->next;
//將頭指針所指向的下一個結點的地址,賦給新創建結點的next
head->next= node;
//將新創建的結點的地址賦給頭指針的下一個結點
尾插法:將新結點插到當前單鏈表的表尾處
end->next = node;
//將新開闢的node的地址賦給head的下一個結點地址
end = node;
//將新建的結點node的地址賦給尾結點end
(2)單鏈表中刪除結點
ListDelete (&L, i, &e):刪除單鏈表L的第i個結點,將結點元素值賦給e。
利用循環操作將p指針定位到第i-1個元素位置,用q指針指向第i個結點 位置並將元素值賦給e,讓第i-1個元素的指針域指向第i+1個元素,然後 釋放q結點;單鏈表的刪除標準語句序列爲:
- q = p->next;
- p->next = q->next;
- e = q->data;
三、依據的基本原理
整個程序的流程看主函數,具體函數實現過程請看第四點,爲方便講解,我直接在代碼後通過註釋的方式講解原理:
int main(int argc, int argv[]) #定義主函數
{
int opt = 0; #定義變量opt
int num = 0; #定義變量num
//創建鏈表
printf("請創建一個鏈表:\n");
pNode phead = create_list(); #運行自定義的創建鏈表函數
//打印輸出鏈表
printf("打印輸出鏈表:\n");
traverse_list(phead); #運行自定義的輸出鏈表函數
//在數字key前邊插入數字data
int key; #定義變量key
int data; #定義變量data
Node node;
printf("在數字幾前插入:\n");
scanf("%d",&data); #輸入
printf("輸入你想要插入的數字:\n");
scanf("%d",&key); #輸入想插入的數字
insertnode_bypre(phead,node,key,data); #運行自定義的插入函數
traverse_list(phead); #運行自定義的輸出鏈表函數
//在數字key1後邊插入數字data1
int key1;
int data1; #定義變量
Node node1;
printf("在數字幾後插入:\n");
scanf("%d",&data1);
printf("輸入你想要插入的數字:\n");
scanf("%d",&key1);
insertnode_byback(phead,node,key1,data1); #後插法
traverse_list(phead); #運行自定義的輸出鏈表函數
//刪除節點
int deldata;
printf("刪除數字:\n");
scanf("%d",&deldata);
deletenode(phead, deldata); #運行自定義的刪除結點函數
traverse_list(phead); #運行自定義的輸出鏈表函數
//查找數字,輸出位置
printf("輸入想要查找的數字:\n");
scanf("%d",&num);
searchnode(phead,num); #運行自定義的按值查找函數
return 0;
}
總的來說,該程序先創建一個鏈表,用戶可根據需要選擇創建的鏈表長度,並給鏈表賦值,創建成功後,輸出鏈表.
然後分別使用前插法與後插法插入數據隨後刪除數據.
最後查找某個數據所在的位置.至此,程序結束.
四、實驗步驟
這是一個用結構體寫的程序,拆開,會很好理解.
程序一開始,就用結構體定義結點,把struct Node *定義爲新類型pNode,是一個結構體的指針。隨後,自定義了7個函數,分別是初始化一個鏈表結點, 創建鏈表函數, 遍歷鏈表, 按值查找操作, 前插法, 後插法, 刪除結點.
爲了便於讀者理解,我還是通過註釋的方式進行講解:
//(1)初始化一個鏈表結點
pNode init_node(Node *pnode, int data)
{
pnode = (Node *)malloc(sizeof(Node));
pnode -> data = data;//初始化數字域
pnode -> next = NULL;//初始化指針域
return pnode;
}
//創建鏈表函數
pNode create_list()
{
int i; // 用於下面循環
int len; // 用來存放有效節點的字數
int val; // 用於臨時存放用戶輸入的數據
pNode pHead = (pNode)malloc(sizeof(Node)); // 分配一個不存放有效數據的頭結點
pNode pTail = pHead; //鏈表的最後一個節點
pTail->next = NULL; // 最後一個節點的指針置爲空
printf("請輸入節點個數:");
scanf("%d", &len);
for (i = 0; i < len; i++)
{
printf("第 %d 個節點的數值:", i + 1);
scanf("%d", &val);
pNode pNew = (pNode)malloc(sizeof(Node)); //爲節點分配空間
//將用戶輸入的數據賦給節點的成員,將最後一個節點的指針指向
//下一個新的節點,將新節點中的指針置爲空,將新節點賦給最後的一個節點
pNew -> data = val; //將用戶輸入的數據賦給節點的成員
pTail -> next = pNew; //將最後一個節點的指針指向下一個新的節點
pNew -> next = NULL; //將新節點中的指針置爲空
pTail = pNew; //將新節點賦給最後的一個節點
printf("successful!");
}
return pHead; //返回頭節點
}
//(2)在鏈表中插入一個新結點。
//前插法
pNode insertnode_bypre(Node *phead, Node node,int data,int key)
{
Node *pnode = init_node(&node, data);//初始化插入的結點
Node *ptmp = phead;
if (phead == NULL)//鏈表爲空,直接返回初始化的值
{
return pnode;
}
else if (phead->data == key)//處理的第一個結點是否爲目標結點
{
phead = pnode;
pnode->next = ptmp;
}
else
{
while((ptmp->next != NULL) && (ptmp->next->data != key))
{
ptmp = ptmp->next;
}
if (ptmp->next == NULL)//沒有找到的情況
{
printf("insert key NOT FOUND\n");
}
else//把新結點插入到目標結點的前面
{
ptmp = (Node *)malloc(sizeof(Node)); //分配一個Node類型大小的內存空間,並把分配空間的首地址強制轉換成Node *類型的
ptmp->data = data; // 爲新結點的數據域賦值
ptmp->next = phead->next; // 將頭指針所指向的下一個結點的地址,賦給新創建結點的next
phead->next = ptmp; // 將新創建的結點的地址賦給頭指針的下一個結點
}
}
printf("successful!");
return phead;
}
//後插法
pNode insertnode_byback(Node *phead,Node node ,int data,int key)
{
Node *pnode = init_node(&node, data);//初始化插入的結點
Node *ptmp = searchnode(phead,key);//查找目標結點
if (ptmp == NULL)//鏈表爲空,或者沒有找到
{
printf("Link is empty or not found key!\n");
return phead;
}
if (ptmp->next == NULL)//如果key爲最後一個結點
{
ptmp->next = pnode;
}
else//將新結點插入到目標結點的後面
{
ptmp = (Node *)malloc(sizeof(Node)); //分配一個Node類型大小的內存空間,並把分配空間的首地址強制轉換成Node *類型的
ptmp -> next = NULL; // 初始化頭結點指向的下一個地址爲 NULL
phead -> next = ptmp;
phead = phead->next;
}
printf("successful!");
return phead;
}
// (3)刪除鏈表中的某一個結點。
pNode deletenode(Node *phead, int key)
{
Node *ptmp = phead;
Node *tmp = NULL;
if (phead == NULL)//處理鏈表爲空的情況
{
printf("Link is empty,delete fail!\n");
return NULL;
}
else if(phead->data == key)//單獨處理第一個結點
{
phead = phead->next;
free(ptmp); //釋放目標結點
ptmp = NULL;
}
else
{
while (ptmp->next != NULL && ptmp->next->data != key)//沒找&&沒有找到
{
ptmp = ptmp->next;
}
if (ptmp->next == NULL)//沒有找到
{
printf("delete key is not found!\n");
return phead;
}
if (ptmp->next->data == key)//找到目標結點並刪除
{
tmp = ptmp->next;
ptmp->next = tmp->next;
free(tmp); //釋放目標結點
tmp = NULL;
}
}
printf("successful!");
return phead;
}
// (4)在鏈表中查找某結點並返回其位置。
pNode searchnode(Node *phead,int key)
{
Node *ptmp = phead;
int i = 0;
if (ptmp == NULL) //查找結點,判斷該結點是否存在
{
return NULL;
}
while (ptmp->data != key && ptmp->next != NULL)
{
i=i+1;
ptmp = ptmp->next;
}
if (ptmp -> data == key)
{
printf("所在位置爲:%d\n",i);
return 0;
}
if (ptmp->next == NULL)
{
printf("該數字不在鏈表中\n");
return NULL;
}
}
//(5)打印輸出鏈表中的結點元素值。
void traverse_list(pNode pHead)
{
pNode p = pHead->next; //將頭節點的指針給予臨時節點p
while (NULL != p) //節點p不爲空,循環
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
五、實驗結果及分析
六、附錄(程序源碼)
#include <stdio.h>
#include <stdlib.h>
typedef struct node{ //用結構體定義結點
int data;
struct node *next;
}Node, *pNode; //把struct Node *定義爲新類型pNode,是一個結構體的指針。
//初始化一個鏈表結點
pNode init_node(Node *pnode, int data);
//創建鏈表函數
pNode create_list();
//遍歷鏈表
void traverse_list(pNode pHead);
//按值查找操作
pNode searchnode(Node *phead, int key);
//前插法
pNode insertnode_bypre(Node *phead, Node node, int data, int key);
//後插法
pNode insertnode_byback(Node *phead, Node node, int data, int key);
//刪除結點
pNode deletenode(Node *phead, int key);
//(1)初始化一個鏈表結點
pNode init_node(Node *pnode, int data)
{
pnode = (Node *)malloc(sizeof(Node));
pnode -> data = data;//初始化數字域
pnode -> next = NULL;//初始化指針域
return pnode;
}
//創建鏈表函數
pNode create_list()
{
int i; // 用於下面循環
int len; // 用來存放有效節點的字數
int val; // 用於臨時存放用戶輸入的數據
pNode pHead = (pNode)malloc(sizeof(Node)); // 分配一個不存放有效數據的頭結點
pNode pTail = pHead; //鏈表的最後一個節點
pTail->next = NULL; // 最後一個節點的指針置爲空
printf("請輸入節點個數:");
scanf("%d", &len);
for (i = 0; i < len; i++)
{
printf("第 %d 個節點的數值:", i + 1);
scanf("%d", &val);
pNode pNew = (pNode)malloc(sizeof(Node)); //爲節點分配空間
//補充代碼,將用戶輸入的數據賦給節點的成員,將最後一個節點的指針指向
//下一個新的節點,將新節點中的指針置爲空,將新節點賦給最後的一個節點
pNew -> data = val; //將用戶輸入的數據賦給節點的成員
pTail -> next = pNew; //將最後一個節點的指針指向下一個新的節點
pNew -> next = NULL; //將新節點中的指針置爲空
pTail = pNew; //將新節點賦給最後的一個節點
printf("successful!");
}
return pHead; //返回頭節點
}
//(2)在鏈表中插入一個新結點。
//前插法
pNode insertnode_bypre(Node *phead, Node node,int data,int key)
{
Node *pnode = init_node(&node, data);//初始化插入的結點
Node *ptmp = phead;
if (phead == NULL)//鏈表爲空,直接返回初始化的值
{
return pnode;
}
else if (phead->data == key)//處理的第一個結點是否爲目標結點
{
phead = pnode;
pnode->next = ptmp;
}
else
{
while((ptmp->next != NULL) && (ptmp->next->data != key))
{
ptmp = ptmp->next;
}
if (ptmp->next == NULL)//沒有找到的情況
{
printf("insert key NOT FOUND\n");
}
else//把新結點插入到目標結點的前面
{
ptmp = (Node *)malloc(sizeof(Node)); //分配一個Node類型大小的內存空間,並把分配空間的首地址強制轉換成Node *類型的
ptmp->data = data; // 爲新結點的數據域賦值
ptmp->next = phead->next; // 將頭指針所指向的下一個結點的地址,賦給新創建結點的next
phead->next = ptmp; // 將新創建的結點的地址賦給頭指針的下一個結點
}
}
printf("successful!");
return phead;
}
//後插法
pNode insertnode_byback(Node *phead,Node node ,int data,int key)
{
Node *pnode = init_node(&node, data);//初始化插入的結點
Node *ptmp = searchnode(phead,key);//查找目標結點
if (ptmp == NULL)//鏈表爲空,或者沒有找到
{
printf("Link is empty or not found key!\n");
return phead;
}
if (ptmp->next == NULL)//如果key爲最後一個結點
{
ptmp->next = pnode;
}
else//將新結點插入到目標結點的後面
{
ptmp = (Node *)malloc(sizeof(Node)); //分配一個Node類型大小的內存空間,並把分配空間的首地址強制轉換成Node *類型的
ptmp -> next = NULL; // 初始化頭結點指向的下一個地址爲 NULL
phead -> next = ptmp;
phead = phead->next;
}
printf("successful!");
return phead;
}
// (3)刪除鏈表中的某一個結點。
pNode deletenode(Node *phead, int key)
{
Node *ptmp = phead;
Node *tmp = NULL;
if (phead == NULL)//處理鏈表爲空的情況
{
printf("Link is empty,delete fail!\n");
return NULL;
}
else if(phead->data == key)//單獨處理第一個結點
{
phead = phead->next;
free(ptmp); //釋放目標結點
ptmp = NULL;
}
else
{
while (ptmp->next != NULL && ptmp->next->data != key)//沒找&&沒有找到
{
ptmp = ptmp->next;
}
if (ptmp->next == NULL)//沒有找到
{
printf("delete key is not found!\n");
return phead;
}
if (ptmp->next->data == key)//找到目標結點並刪除
{
tmp = ptmp->next;
ptmp->next = tmp->next;
free(tmp); //釋放目標結點
tmp = NULL;
}
}
printf("successful!");
return phead;
}
// (4)在鏈表中查找某結點並返回其位置。
pNode searchnode(Node *phead,int key)
{
Node *ptmp = phead;
int i = 0;
if (ptmp == NULL) //查找結點,判斷該結點是否存在
{
return NULL;
}
while (ptmp->data != key && ptmp->next != NULL)
{
i=i+1;
ptmp = ptmp->next;
}
if (ptmp -> data == key)
{
printf("所在位置爲:%d\n",i);
return 0;
}
if (ptmp->next == NULL)
{
printf("該數字不在鏈表中\n");
return NULL;
}
}
//(5)打印輸出鏈表中的結點元素值。
void traverse_list(pNode pHead)
{
pNode p = pHead->next; //將頭節點的指針給予臨時節點p
while (NULL != p) //節點p不爲空,循環
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//主函數
int main(int argc, int argv[])
{
int opt = 0;
int num = 0;
//創建鏈表
printf("請創建一個鏈表:\n");
pNode phead = create_list();
//打印輸出鏈表
printf("打印輸出鏈表:\n");
traverse_list(phead);
//在數字key前邊插入數字data
int key;
int data;
Node node;
printf("在數字幾前插入:\n");
scanf("%d",&data);
printf("輸入你想要插入的數字:\n");
scanf("%d",&key);
insertnode_bypre(phead,node,key,data);
traverse_list(phead);
//在數字key1後邊插入數字data1
int key1;
int data1;
Node node1;
printf("在數字幾後插入:\n");
scanf("%d",&data1);
printf("輸入你想要插入的數字:\n");
scanf("%d",&key1);
insertnode_byback(phead,node,key1,data1);
traverse_list(phead);
//刪除節點
int deldata;
printf("刪除數字:\n");
scanf("%d",&deldata);
deletenode(phead, deldata);
traverse_list(phead);
//查找數字,輸出位置
printf("輸入想要查找的數字:\n");
scanf("%d",&num);
searchnode(phead,num);
return 0;
}
以上就是全部內容,如果大家有更好的方法,歡迎大家與我討論