資料結構——單連結串列介面實現(C語言)
單連結串列的介面實現
github程式碼下載
github程式碼:
https://github.com/Kyrie-leon/Data_Structures/tree/main/ListNode
一、連結串列的概念及結構
1.1 概念
連結串列是一種物理結構上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。
1.2 結構
二、連結串列的介面實現
2.1 連結串列的儲存定義
typedef int SLTDataType;
//單連結串列的定義
typedef struct SListNode
{
SLTDataType data;
struct SListNode * next; //next指向當前節點的下一個節點
}SListNode;
2.2 動態申請一個節點
申請一個節點首先使用malloc開闢一塊結構記憶體
然後將資料元素x放入data資料區
將next置空
//2.2 動態申請一個節點
SListNode * BuyListNode(SLTDataType x)
{
SListNode * plist=(SListNode *)malloc(sizeof(SListNode));
//判斷申請是否成功
if (plist==NULL)
{
printf("申請新節點失敗\n");
exit(-1);
}
plist->data = x;
plist->next = NULL;
return plist;
}
2.3 單連結串列列印
//2.3 單連結串列列印
void SListPrint(SListNode * plist)
{
//列印連結串列
while (plist)
{
printf("%d->", plist->data);
plist = plist->next; //節點指向下一個
}
printf("NULL\n");
}
2.4 單連結串列尾插
-
首先申請一個新節點
-
判斷連結串列是否為空,如果為空則直接將新節點插入
-
不是空的話,遍歷連結串列找到尾節點
-
找到後,申請新節點,讓原連結串列尾節點指向新節點
注意:由於尾插可能存在空連結串列的情況,因此當連結串列為空時傳入一級指標不會改變連結串列的狀態,所以傳入二級指標。
//2.4 單連結串列尾插
void SListPushBack(SListNode** pplist, SLTDataType x)
{
//申請一個新節點
SListNode* NewNode = BuyListNode(x);
//判斷連結串列是否為空,如果為空則申請節點直接插入,否則找到尾節點插入
if ((*pplist) == NULL)
{
*pplist = NewNode;
}
else
{
//定義一個當前節點tail去找連結串列的尾節點
SListNode* tail = *pplist;
//遍歷節點找尾節點
while (tail->next)
{
tail = tail->next;
}
//尾節點的next指向新節點
tail->next = NewNode;
}
}
2.5 單連結串列頭插
- 首先申請新節點
- 判斷連結串列是否為空,若為空直接插入
- 不為空,讓NewNode的next指向Plist,然後讓Plist指向NewNode
//2.5 單連結串列頭插
void SListPushFront(SListNode** pplist, SLTDataType x)
{
//申請新節點
SListNode * NewNode = BuyListNode(x);
//判斷連結串列是否空
if (*pplist == NULL)
{
//連結串列為空直接插入
*pplist = NewNode;
}
else
{
NewNode->next = *pplist; //新節點next指向pplist
*pplist=NewNode; //更新頭結點
}
}
2.6 單連結串列尾刪
尾刪有三種情況:
-
單連結串列為空則返回
-
單連結串列只有一個節點,直接刪除
-
單連結串列有一個以上節點,定義兩個指標,一個指向尾節點,一個指向尾節點前的一個節點。首先找到尾節點刪除,
然後將prev的next置空
//2.6 單連結串列尾刪
void SListPopBack(SListNode** pplist)
{
//1.單連結串列為空
if (*pplist == NULL)
{
return;
}
//2.單連結串列只有一個節點
else if((*pplist)->next==NULL)
{
free(*pplist);
*pplist = NULL;
}
//3.單連結串列有一個以上節點
else
{
//tali指向第1個節點,prev為空
SListNode * prev = NULL;
SListNode * tail = *pplist;
//遍歷連結串列找到尾節點
while (tail->next!=NULL)
{
//注意先後順序,prev先走才不會丟失節點
//prev向後走一個節點
prev = tail;
//tail向後走一個節點
tail = tail->next;
}
//刪除尾節點
free(tail);
//prev作為新的尾節點
prev->next = NULL;
}
}
2.7 單連結串列頭刪
連結串列三種情況同上
首先找到頭結點,
讓*pplist指向下一個節點
刪除頭結點
//2.7 單連結串列頭刪
void SListPopFront(SListNode** pplist)
{
//1.空單連結串列
if (*pplist == NULL)
{
return;
}
//2.一個節點
else if ((*pplist)->next == NULL)
{
free(*pplist);
*pplist = NULL;
}
//3.一個以上
else
{
SListNode * phead = *pplist;
//現移動刪除後的頭結點
*pplist = phead->next;
//再釋放原來的頭結點
free(phead);
}
}
2.8 單連結串列查詢
//2.8 單連結串列查詢
SListNode * SListFind(SListNode * plist, SLTDataType x)
{
SListNode * cur = plist;
//1.空連結串列直接返回
//遍歷連結串列
while (cur)
{
//如果找節點值等於x則返回
if (x == cur->data)
{
return cur;
}
//沒找到繼續遍歷
cur = cur->next;
}
return NULL;
}
2.9 單連結串列任意位置之後插入
在pos位置之後插入新節點容易實現,首先讓新節點指向當前節點cur的下一個節點,然後讓cur當前節點指向新節點
//2.9 單連結串列在任意位置之後插入x
void SListInsertAfter(SListNode* pos, SLTDataType x)
{
assert(pos);
SListNode * newNode = BuyListNode(x);
newNode->next = pos->next;
pos->next = newNode;
}
2.10 單連結串列刪除任意位置之後的值
//2.10 單連結串列刪除任意位置之後的值
void SListEraseAfter(SListNode* pos)
{
assert(pos);
if (pos->next)
{
SListNode * next = pos->next; //找到pos位置後面的節點儲存起來,防止刪除後丟失
pos->next = next->next; //pos位置節點指向next後的節點
free(next); //釋放pos後的節點
}
}
三、多檔案實現
3.1 ListNode.h
#ifndef _LISTNODE_H
#define _LISTNODE_H
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
//單連結串列的定義
typedef struct SListNode
{
SLTDataType data; //data
struct SListNode * next; //next指向當前節點的下一個節點
}SListNode;
//動態申請一個節點
SListNode * BuyListNode(SLTDataType x);
//單連結串列列印
void SListPrint(SListNode * plist);
//單連結串列尾插
void SListPushBack(SListNode** pplist, SLTDataType x);
//單連結串列頭插
void SListPushFront(SListNode** pplist, SLTDataType x);
//單連結串列尾刪
void SListPopBack(SListNode** pplist);
//單連結串列頭刪
void SListPopFront(SListNode** pplist);
//單連結串列查詢
SListNode * SListFind(SListNode * plist, SLTDataType x);
//單連結串列在任意位置之後插入x
void SListInsertAfter(SListNode* pos, SLTDataType x);
//單連結串列刪除任意位置之後的值
void SListEraseAfter(SListNode* pos);
//單連結串列的銷燬
void SListDestory(SListNode* plist);
#endif
3.2 ListNode.c
#include "ListNode.h"
//2.2 動態申請一個節點
SListNode * BuyListNode(SLTDataType x)
{
SListNode * plist=(SListNode *)malloc(sizeof(SListNode));
//判斷申請是否成功
if (plist==NULL)
{
printf("申請新節點失敗\n");
exit(-1);
}
plist->data = x;
plist->next = NULL;
return plist;
}
//2.3 單連結串列列印
void SListPrint(SListNode * plist)
{
//列印連結串列
while (plist)
{
printf("%d->", plist->data);
plist = plist->next; //節點指向下一個
}
printf("NULL\n");
}
//2.4 單連結串列尾插
void SListPushBack(SListNode** pplist, SLTDataType x)
{
//申請一個新節點
SListNode* NewNode = BuyListNode(x);
//判斷連結串列是否為空,如果為空則申請節點直接插入,否則找到尾節點插入
if ((*pplist) == NULL)
{
*pplist = NewNode;
}
else
{
//定義一個當前節點tail去找連結串列的尾節點
SListNode* tail = *pplist;
//遍歷節點找尾節點
while (tail->next)
{
tail = tail->next;
}
//尾節點的next指向新節點
tail->next = NewNode;
}
}
//2.5 單連結串列頭插
void SListPushFront(SListNode** pplist, SLTDataType x)
{
//申請新節點
SListNode * NewNode = BuyListNode(x);
//判斷連結串列是否空
if (*pplist == NULL)
{
//連結串列為空直接插入
*pplist = NewNode;
}
else
{
NewNode->next = *pplist; //新節點next指向pplist
*pplist=NewNode; //更新頭結點
}
}
//2.6 單連結串列尾刪
void SListPopBack(SListNode** pplist)
{
//1.單連結串列為空
if (*pplist == NULL)
{
return;
}
//2.單連結串列只有一個節點
else if((*pplist)->next==NULL)
{
free(*pplist);
*pplist = NULL;
}
//3.單連結串列有一個以上節點
else
{
//tali指向第1個節點,prev為空
SListNode * prev = NULL;
SListNode * tail = *pplist;
//遍歷連結串列找到尾節點
while (tail->next!=NULL)
{
//注意先後順序,prev先走才不會丟失節點
//prev向後走一個節點
prev = tail;
//tail向後走一個節點
tail = tail->next;
}
//刪除尾節點
free(tail);
//prev作為新的尾節點
prev->next = NULL;
}
}
//2.7 單連結串列頭刪
void SListPopFront(SListNode** pplist)
{
//1.空單連結串列
if (*pplist == NULL)
{
return;
}
//2.一個節點
else if ((*pplist)->next == NULL)
{
free(*pplist);
*pplist = NULL;
}
//3.一個以上
else
{
SListNode * phead = *pplist;
//現移動刪除後的頭結點
*pplist = phead->next;
//再釋放原來的頭結點
free(phead);
}
}
//2.8 單連結串列查詢
SListNode * SListFind(SListNode * plist, SLTDataType x)
{
SListNode * cur = plist;
//1.空連結串列直接返回
//遍歷連結串列
while (cur)
{
//如果找節點值等於x則返回
if (x == cur->data)
{
return cur;
}
//沒找到繼續遍歷
cur = cur->next;
}
return NULL;
}
//2.9 單連結串列在任意位置之後插入x
void SListInsertAfter(SListNode* pos, SLTDataType x)
{
assert(pos);
SListNode * newNode = BuyListNode(x);
newNode->next = pos->next;
pos->next = newNode;
}
//2.10 單連結串列刪除任意位置之後的值
void SListEraseAfter(SListNode* pos)
{
assert(pos);
if (pos->next)
{
SListNode * next = pos->next; //找到pos位置後面的節點儲存起來,防止刪除後丟失
pos->next = next->next; //pos位置節點指向next後的節點
free(next); //釋放pos後的節點
}
}
3.3 test.c
#include "ListNode.h"
//測試單連結串列的頭尾刪除
void TestListNode1()
{
SListNode * Plist=NULL; //定義一個單連結串列
//測試申請一個節點
Plist = BuyListNode(1);
//列印連結串列測試
SListPrint(Plist);
//2.4 單連結串列尾插測試
SListPushBack(&Plist, 2);
SListPushBack(&Plist, 3);
SListPushBack(&Plist, 4);
SListPushBack(&Plist, 5);
SListPrint(Plist);
//2.5 單連結串列頭插
SListPushFront(&Plist, -1);
SListPrint(Plist);
//單連結串列尾刪
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPopBack(&Plist);
//SListPrint(Plist);
//單連結串列頭刪
//SListPopFront(&Plist);
//SListPopFront(&Plist);
//SListPopFront(&Plist);
//SListPopFront(&Plist);
//SListPopFront(&Plist);
//SListPopFront(&Plist);
//SListPopFront(&Plist);
//SListPopFront(&Plist);
//SListPrint(Plist);
//2.8 單連結串列查詢
SListNode * pos = SListFind(Plist, 3);
SListPrint(pos);
//2.9 單連結串列在任意位置之後插入x
SListInsertAfter(pos, 30);
SListPrint(Plist);
//2.10 單連結串列刪除任意位置之後的值
SListEraseAfter(pos);
SListPrint(Plist);
}
int main()
{
TestListNode1();
system("pause");
return 0;
}
相關文章
- 用c語言實現資料結構——單連結串列C語言資料結構
- 【資料結構】用C語言實現單連結串列及其常見操作資料結構C語言
- 資料結構 - 單連結串列 C++ 實現資料結構C++
- 資料結構_連結串列的原理與應用1_單連結串列(基於C語言實現)資料結構C語言
- 資料結構——單連結串列的C++實現資料結構C++
- “c語言+結構體+連結串列”實現名片系統C語言結構體
- js實現資料結構--單連結串列JS資料結構
- 基數排序-單連結串列實現【資料結構與演算法分析(c 語言描述)】排序資料結構演算法
- 資料結構__連結串列_單連結串列的初始化、插入、刪除、修改、查詢列印(基於C語言實現)資料結構C語言
- 【資料結構】連結串列(單連結串列實現+詳解+原碼)資料結構
- c語言單向連結串列逆轉實現方法C語言
- 資料結構與演算法分析(c 語言描述)多項式 ADT 單連結串列實現資料結構演算法
- C語言資料結構:單向迴圈連結串列的增刪操作C語言資料結構
- 單向迴圈連結串列介面設計(C語言)C語言
- 資料結構-單連結串列、雙連結串列資料結構
- 資料結構_連結串列_單向迴圈連結串列 & 雙向連結串列的初始化、插入、刪除、修改、查詢列印(基於C語言實現)資料結構C語言
- 資料結構筆試題——基於C語言的連結串列功能函式實現資料結構筆試C語言函式
- Go 語言介面及使用介面實現連結串列插入Go
- 資料結構之php實現單向連結串列資料結構PHP
- C語言資料結構:雙向連結串列的增刪操作C語言資料結構
- 資料結構_連結串列_單向迴圈連結串列的初始化、插入、刪除、修改、查詢列印(基於C語言實現)資料結構C語言
- 雙向連結串列介面設計(C語言)C語言
- 資料結構-2.單向連結串列的實現資料結構
- 資料結構--單連結串列(通過陣列實現)資料結構陣列
- 資料結構實驗之連結串列五:單連結串列的拆分資料結構
- 連結串列-單連結串列實現
- 資料結構之單連結串列資料結構
- 資料結構04——單連結串列資料結構
- 資料結構和演算法——Go實現單連結串列並且反轉單連結串列資料結構演算法Go
- Go 語言 結構體連結串列Go結構體
- C語言資料結構:雙向迴圈連結串列的增刪操作C語言資料結構
- 6-C/C++實現資料結構連結串列相關操作C++資料結構
- 單向連結串列————遍歷、查詢、插入結點 (基於C語言實現)C語言
- 演算法與資料結構-連結串列((linked-list)-Java實現單向連結串列演算法資料結構Java
- 資料結構_連結串列_雙向迴圈連結串列的初始化、插入、刪除、修改、查詢列印(基於C語言實現)資料結構C語言
- C語言線性連結串列C語言
- php實現基本資料結構之連結串列PHP資料結構
- 資料結構(雙向連結串列的實現)資料結構