自定義單向迴圈連結串列的增刪改查介面函式
/*******************************************************************
*
- 檔名稱 : 01 單向迴圈連結串列的介面程式
- 檔案作者 : mailLinL@163.com
- 建立日期 : 2024/04/23
- 檔案功能 : 對單向迴圈連結串列的增刪改查功能的定義
- 注意事項 : None
- CopyRight (c) 2024 mailLinL@163.com All Right Reseverd
- *****************************************************************/
定義結構體中資料域的資料型別,使用者可以根據需求修改資料型別
typedef int DataType_t;
構造單向迴圈連結串列的結點,連結串列中所有結點的資料型別應該是相同的
typedef struct CircularLinkedList
{
DataType_t data; //結點的資料域
struct LinkedList *next; //結點的指標域
}CircLList_t;
建立單向迴圈連結串列,空連結串列中有一個頭結點,便於管理該連結串列
/*******************************************************************
*
* 函式名稱: CircLList_Create
* 函式功能: 建立單向迴圈連結串列,空連結串列中有一個頭結點
* 函式引數: none
* 返回結果:
* @Head : 返回頭結點地址便於管理連結串列
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/23
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
//建立一個空單向迴圈連結串列,空連結串列應該有一個頭結點,對連結串列進行初始化
CircLList_t * CircLList_Create(void)
{
//1.建立一個頭結點並對頭結點申請記憶體
CircLList_t *Head = (CircLList_t *)calloc(1,sizeof(CircLList_t));
if (NULL == Head)
{
perror("Calloc memory for Head is Failed");
exit(-1);
}
//2.對頭結點進行初始化,頭結點是不儲存資料域,指標域指向自身,體現“迴圈”思想
Head->next = Head;
//3.把頭結點的地址返回即可
return Head;
}
建立新結點,並返回新結點的地址便於操作
/*******************************************************************
*
* 函式名稱: CircLList_NewNode
* 函式功能: 建立新結點
* 函式引數:
* @data :傳入新建結點的資料域中的值
* 返回結果:
* @New : 返回新建結點地址
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/23
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
//建立新的結點,並對新結點進行初始化(資料域 + 指標域)
CircLList_t * CircLList_NewNode(DataType_t data)
{
//1.建立一個新結點並對新結點申請記憶體
CircLList_t *New = (CircLList_t *)calloc(1,sizeof(CircLList_t));
if (NULL == New)
{
perror("Calloc memory for NewNode is Failed");
return NULL;
}
//2.對新結點的資料域和指標域進行初始化
New->data = data;
New->next = NULL;
return New;
}
向連結串列的開頭插入元素
/*******************************************************************
*
* 函式名稱: CircLList_HeadInsert
* 函式功能: 向連結串列的頭結點中插入元素
* 函式引數:
* @Head :傳入需要操作的連結串列的頭結點地址
* @data :傳入需要插入的結點中的資料域
* 返回結果:
* @bool : 返回插入操作是否成功
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/23
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
//頭插
bool CircLList_HeadInsert(CircLList_t *Head,DataType_t data)
{
//1.新建結點並傳入結點中的資料域中的值,定義指標記錄新建結點的地址
CircLList_t *New=CircLList_NewNode( data);
if(NULL==New){
return false;
}
//2.定義指標以備份頭結點的地址用作遍歷連結串列
CircLList_t *temp=Head;
//3.判斷連結串列是否為空
if(Head->next==Head){
Head->next=New; //如果為空,讓頭結點的next指標指向新結點,並將NEW結點的next指標指向自身
New->next=New;
}
//4.遍歷連結串列找到單向迴圈連結串列的尾結點
while(temp->next!=Head-next){
temp=temp->next;
}
//5.將新結點插入頭部
temp-next=New;
New->next=Head->next;
return true;
}
向連結串列的尾結點後插入元素
/*******************************************************************
*
* 函式名稱: CircLList_TailInsert
* 函式功能: 向連結串列的尾結點後插入元素
* 函式引數:
* @Head :傳入需要操作的連結串列的頭結點地址
* @data :傳入需要插入的結點中的資料域
* 返回結果:
* @bool : 返回插入操作是否成功
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/23
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
//尾插
bool CircLList_TailInsert(CircLList_t *Head,DataType_t data)
{
//1.新建結點並傳入結點中的資料域中的值,定義指標記錄新建結點的地址
CircLList_t *New=CircLList_NewNode( data);
if(NULL==New){
return false;
}
//2.定義指標以備份頭結點的地址用作遍歷連結串列
CircLList_t *temp=Head;
//3.判斷連結串列是否為空
if(Head->next==Head){
Head->next=New; //如果為空,讓頭結點的next指標指向新結點,並將NEW結點的next指標指向自身
New->next=New;
}
//4.遍歷連結串列找到單向迴圈連結串列的尾結點
while(temp->next!=Head-next){
temp=temp->next;
}
//5.將新結點插入連結串列尾結點之後
New->=Head->next ;
temp->next=New;
return true;
}
向連結串列的目標結點後插入元素
/*******************************************************************
*
* 函式名稱: CircLList_DestInsert
* 函式功能: 向連結串列的目標結點後插入元素
* 函式引數:
* @Head :傳入需要操作的連結串列的頭結點地址
* @data :傳入需要插入的結點中的資料域
* @destval :傳入需要插入的目標結點資料域
* 返回結果:
* @bool : 返回插入操作是否成功
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/23
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
//指定位置插入
bool CircLList_DestInsert(CircLList_t *Head,DataType_t destval,DataType_t data)
{
//1.新建結點並傳入結點中的資料域中的值,定義指標記錄新建結點的地址
CircLList_t *New=CircLList_NewNode( data);
if(NULL==New){
return false;
}
//2.定義指標以備份頭結點的地址用作遍歷連結串列
CircLList_t *temp=Head;
//3.判斷連結串列是否為空
if(Head->next==Head){
Head->next=New; //如果為空,讓頭結點的next指標指向新結點,並將NEW結點的next指標指向自身
New->next=New;
}
//4.遍歷連結串列查詢目標結點的位置
while(temp->data!=destval){
temp=temp->next;
}
//5.將新結點插入目標結點之後
New->next=temp->next;
temp->next=New;
return true;
}
遍歷連結串列
bool CircLList_Print(CircLList_t *Head)
{
//對單向迴圈連結串列的頭結點的地址進行備份
CircLList_t *Phead = Head;
//判斷當前連結串列是否為空,為空則直接退出
if (Head->next == Head)
{
printf("current linkeflist is empty!\n");
return false;
}
//從首結點開始遍歷
while(Phead->next)
{
//把頭結點的直接後繼作為新的頭結點
Phead = Phead->next;
//輸出頭結點的直接後繼的資料域
printf("data = %d\n",Phead->data);
//判斷是否到達尾結點,尾結點的next指標是指向首結點的地址
if (Phead->next == Head->next)
{
break;
}
}
return true;
}
從連結串列刪除與目標值相同的結點
/*******************************************************************
*
* 函式名稱: CircLList_DestInsert
* 函式功能: 從連結串列刪除與目標值相同的結點
* 函式引數:
* @destval :傳入需要刪除的目標結點資料域
* 返回結果:
* @bool : 返回插入操作是否成功
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/23
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
bool CircLList_DestDel(DataType_t destval)
{
//1.判斷當前連結串列是否為空,為空則直接退出
if (Head->next == Head)
{
printf("current linkeflist is empty!\n");
return false;
}
//2.對單向迴圈連結串列的頭結點的地址進行備份,並備份目標結點的直接前驅位置
CircLList_t *Phead = Head->next;
CircLList_t *prev =Head;
while(Phead->data!==destval){
Phead=Phead->next;
prev=prev->next;
if(Phead->next==Head->next){
printf("No target node!");
return false;
}
}
//3.找到結點後判斷該結點的位置並進行刪除操作
if(Head->next==Phead->next&&Head->next==Phead){ //說明該結點是連結串列中的唯一結點
Phead->next=NULL;
Head->next=Head;
free(Phead);
}
else if(Phead->next!=Head->next&&Head->next==Phead){ //說明該結點不是唯一節點且是首結點
Head->next=Phead->next;
Phead->next=NULL;
free(Phead);
}else if(Phead->next!=Head->next&&Head->next!=Phead){ //說明該結點既不是首結點也不是尾結點
prev->next=Phead->next;
Phead->next=NULL;
free(Phead);
}
else if(Head->next!=Phead&&Phead->next==Head->next){ //說明該結點不是唯一結點並且是尾結點
prev->next=Head->next;
Phead->next=NULL:
free(Phead);
}
return true;
}
總結:
對單向迴圈連結串列進行操作前,需判斷連結串列是否為空
對非空單向迴圈連結串列操作時,需要判別操作項是否在特殊位置。(如首結點或尾結點)
對僅有一個結點的連結串列操作時,需要注意頭結點指標域指向的位置