循环单链表算法库

学习贺老师数据结构

数据结构之自建算法库——循环单链表_循环单链表 csdn-CSDN博客​​​​​​

整理总结出的循环单链表算法库

v1.0 : 基本实现功能

v2.0(2024.4.6):

修复Delete_SpecificLocate_CyclicList()删除节点函数bug,添加验证删除节点是否超范围判断

目录

1.主要功能:

2. 循环链表头文件

3. 循环链表库函数

4. main.cpp测试函数

5. 运行展示:

V2.0

v1.0 bug复现

1.主要功能

2. 循环链表头文件

3. 循环链表库函数

4. main.cpp测试函数

5. 运行展示:



V1.0

1.主要功能:

//(1)头插法建立循环单链表
void Create_CyclicList_Head(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number);
//(2)尾插法建立单链表
void Create_CyclicList_Tail(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number);
//(3)输出循环单链表
void Display_CyclicList(singleLinkList_Cyclic *L);
//(4)初始化循环单链表
void Init_CyclicList(singleLinkList_Cyclic *&L);
//(5)销毁循环单链表
void Destroy_CyclicList(singleLinkList_Cyclic *&L);
//(6)判断循环单链表是否为空
bool  Empty_CyclicList(singleLinkList_Cyclic *L);
//(7)求循环单链表数据元素个数(不包括头结点)
int Length_CyclicList(singleLinkList_Cyclic *L);
//(8) 查找特定元素值,在循环单链表中的位置
int SpecificValue_Location_CyclicList(singleLinkList_Cyclic *L, ElemType specific_value);
//(9) 取出循环单链表中 特定位置的元素值
bool SpecificLocate_Value_CyclicList(singleLinkList_Cyclic *L, int specific_locate,ElemType &get_value);
//(10) 把特定的节点值, 插入到循环单链表特定位置
bool InsertElement_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType insert_value);
//(11) 删除特定位置的节点值
bool Delete_SpecificLocate_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType &delete_value);

2. 循环链表头文件

Cyclic_singleLinkList.h 

#ifndef CYCLIC_SINGLELINKLIST_H_INCLUDE
#define CYCLIC_SINGLELINKLIST_H_INCLUDE#include "stdio.h"
#include "malloc.h"//循环单链表基本运算函数
typedef int ElemType;
typedef struct Cyclic_Node
{ElemType data;struct Cyclic_Node *next;
}singleLinkList_Cyclic;//(1)头插法建立循环单链表
void Create_CyclicList_Head(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number);
//(2)尾插法建立单链表
void Create_CyclicList_Tail(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number);
//(3)输出循环单链表
void Display_CyclicList(singleLinkList_Cyclic *L);
//(4)初始化循环单链表
void Init_CyclicList(singleLinkList_Cyclic *&L);
//(5)销毁循环单链表
void Destroy_CyclicList(singleLinkList_Cyclic *&L);
//(6)判断循环单链表是否为空
bool  Empty_CyclicList(singleLinkList_Cyclic *L);
//(7)求循环单链表数据元素个数(不包括头结点)
int Length_CyclicList(singleLinkList_Cyclic *L);//(8) 查找特定元素值,在循环单链表中的位置
int SpecificValue_Location_CyclicList(singleLinkList_Cyclic *L, ElemType specific_value);//(9) 取出循环单链表中 特定位置的元素值
bool SpecificLocate_Value_CyclicList(singleLinkList_Cyclic *L, int specific_locate,ElemType &get_value);//(10) 把特定的节点值, 插入到循环单链表特定位置
bool InsertElement_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType insert_value);
//(11) 删除特定位置的节点值
bool Delete_SpecificLocate_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType &delete_value);#endif     //CYCLI_SINGLELINKLIST_H_INCLUDE

3. 循环链表库函数

Cyclic_singleLinkList.cpp

#include "Cyclic_singleLinkList.h"/**************************************************
(1)函数名: Create_CyclicList_Head
功  能: 头插法建立循环单链表
参  数: (1)singleLinkList_Cyclic *&L: 要建立并传回去的循环单链表指针地址(2)ElemType Array_used[]: 要使用的数组数据(3)int Array_number: 数组的长度
注 意: ①我们是按照单链表方法建立,最后找到尾指针,再形成闭环
思 路:  (1)创建头结点(2)头结点置空(3)根据数据创建新节点,并利用头插法插入(4)查找尾结点(5)形成闭环
返回值: 无
**************************************************/
void Create_CyclicList_Head(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number)
{int counter;singleLinkList_Cyclic *newnode,*tailnode;L = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic)); //创建头结点L->next = NULL;for(counter = 0; counter < Array_number; counter++){newnode = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));  //创建新节点newnode->data = Array_used[counter];newnode->next = L->next;         //将newnode插在原开始结点之前,头结点之后L->next = newnode;}tailnode = L;while(tailnode->next != NULL) //①查找尾结点, 从而将其指向头结点{tailnode = tailnode->next;}tailnode->next = L;         // 形成闭环}/**************************************************
(2)函数名: Create_CyclicList_Tail
功  能: 尾插法建立单链表
参  数: (1)singleLinkList_Cyclic *&L: 要建立并传回去的循环单链表指针地址(2)ElemType Array_used[]: 要使用的数组数据(3)int Array_number: 数组的长度
注 意:   我们是按照单链表建立的方法进行建立,最后尾指针指向头结点即可
思 路:   (1)定义新节点,尾指针节点,数组遍历序号(2)创建头结点,并置空后继指针(3)按照数组顺序,新建节点,并利用尾插法插入链表尾部(4)插入完成,尾指针指向头结点
返回值:   无
**************************************************/
void Create_CyclicList_Tail(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number)
{int counter;singleLinkList_Cyclic *newNode,*tailNode;L = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));L->next = NULL;tailNode = L;for(counter = 0; counter < Array_number; counter++){newNode = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));newNode->data = Array_used[counter];tailNode->next = newNode;tailNode = newNode;}tailNode->next = L;}/**************************************************
(3)函数名: Display_CyclicList
功  能: 输出展示循环单链表
参  数:(1)singleLinkList_Cyclic *L:要展示的循环单链表
注 意:①因为是循环单链表,所以结束条件是, 指针指向头结点
思 路:  (1)定义遍历节点(2)判断是否为空(L == L->next)(3)从数据节点开始遍历输出(4)不结束接着遍历输出
返回值: 无
**************************************************/
void Display_CyclicList(singleLinkList_Cyclic *L)
{singleLinkList_Cyclic *showNode;showNode = L->next;if(showNode == L){printf("hey, it is Empty!");     //为空,无法输出}while(showNode != L)//①{printf("%d",showNode->data);printf(" ");showNode = showNode->next;}printf("\n");
}/**************************************************
(4)函数名: Init_CyclicList
功  能: 初始化循环单链表
参  数: singleLinkList_Cyclic *&L:要初始化的循环单链表指针地址
返回值: 无
**************************************************/void Init_CyclicList(singleLinkList_Cyclic *&L)
{L = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));L->next = L;    //初始化头结点指向自己
}/**************************************************
(5)函数名: Destroy_CyclicList
功  能: 释放循环单链表的节点空间,
参  数: singleLinkList_Cyclic *&L:要销毁的循环单链表
注 意: ①防止野指针被函数利用后, 飘飞②防止遍历指针信息被删除后,找不到后继信息③循环单链表,结束条件是 尾指针指向头结点
思 路:   (1)定义遍历指针和后继指针(2)规划好nowNode和backNode关系(3) nowNode遍历删除,backNode后移,直到backNode == L,退出(4)接着释放nowNode,并且防止野指针飘飞,①返回值:  无
**************************************************/
void Destroy_CyclicList(singleLinkList_Cyclic *&L)
{singleLinkList_Cyclic *nowNode;singleLinkList_Cyclic *backNode;    //②nowNode = L;backNode = nowNode->next;while(backNode != L)        //③{free(nowNode);nowNode = backNode;backNode = backNode->next;}free(nowNode);L->next = L;    //①
}/**************************************************
(6)函数名: Empty_CyclicList
功  能: 判断循环单链表是否为空
参  数: singleLinkList_Cyclic *L:要参与判断的循环单链表
返回值: bool:是否为空? true:false
**************************************************/
bool  Empty_CyclicList(singleLinkList_Cyclic *L)
{return (L->next == L);
}
/**************************************************
(7)函数名: Length_CyclicList
功  能: 求循环单链表数据元素个数(不包括头结点)
参  数: singleLinkList_Cyclic *L :要参与计算的循环单链表
注  意: ① 结束条件:尾指针指向头结点
返回值:  int: 循环单链表数据元素个数
**************************************************/
int Length_CyclicList(singleLinkList_Cyclic *L)
{int counter = 0;singleLinkList_Cyclic *nowNode = L;while(nowNode->next != L)     //①{counter++;nowNode = nowNode->next;}return counter;
}
/**************************************************
(8)函数名:SpecificValue_Location_CyclicList
功  能:找特定元素值,在循环单链表中的位置
参  数:(1)singleLinkList_Cyclic *L:  需要查找的循环单链表(2)ElemType specific_value:   要查找的元素值
注 意: ① 从 L->next开始,即第一个数据元素开始查找,其位置counter伴随②跳出有两种情况:1,找到 2,超范围指向头结点
返回值: int: 返回特定元素值的 位置(0:未找到 , 1~n: 找到)
**************************************************/
int SpecificValue_Location_CyclicList(singleLinkList_Cyclic *L, ElemType specific_value)
{int counter = 1;singleLinkList_Cyclic *nowNode = L->next;   //①while((nowNode != L) && (nowNode->data != specific_value)){counter++;nowNode = nowNode->next;}if(nowNode == L)         //②如果指向头结点,则未找到{return 0;}else{return counter;}}
/**************************************************
(9)函数名:SpecificLocate_Value_CyclicList
功  能:取出循环单链表中 特定位置的元素值
参  数:(1)singleLinkList_Cyclic *L: 要进行遍历查找的循环单链表(2)int specific_locate: 要定位的特定位置(3)ElemType &value: 传回对应的节点数据
注  意:①循环链表,超范围条件是nowNode = L,如果从头开始,nowNode = L,counter = 0,就会默认到头所以从第 L->next开始算,② 从① 开始算的前提是,L有后继节点,也就是L不是空表③ L不是空表, 但是所给位置,超出循环链表长度,仍返回错误④ ②和③其实可以归为一类,都是长度不足,但是为了做区分, 分开了
思  路:(1)定义当前节点和位置序号  (2)从第一个数据节点开始(3) 空表直接跳出          (4)通过对比位置信息 和 检测 节点循环链表是否超范围(5)传回特定位置信息  或者 超范围标志false返回值:  bool: 是否找到特定位置,并传回节点数据? true:false
**************************************************/
bool SpecificLocate_Value_CyclicList(singleLinkList_Cyclic *L, int specific_locate,ElemType &get_value)
{int counter = 1;bool result;singleLinkList_Cyclic *nowNode;nowNode = L->next;     //①if(nowNode == L)     //②{result = false;   //循环链表为空表,跳出}else{while(counter < specific_locate && nowNode != L){counter++;nowNode = nowNode->next;}if(nowNode == L)    //③{result = false;        //位置还未到,链表到头了,长度不足}else{get_value = nowNode->data;result = true;}}return result;
}/**************************************************
(10)函数名: InsertElement_CyclicList
功  能:特定的节点值,插入到循环单链表特定位置
参  数:(1)singleLinkList_Cyclic *&L:要插入的循环单链表(2)int specific_locate: 要插入的特定位置(3)ElemType insert_value: 要插入的特定值思  路: (1)定义遍历节点nowNode,新节点newNode   (2)从头开始遍历,到特定位置(3) 不管是否为空表,第一个位置都可以插入成功,单独摘出(4)  后续遍历nowNode从 nowNode = L->next开始,只能插入到第2~n个位置(5)  查找第(specific_locate-1 )个位置{是否超范围? true:false},将新节点插入其后(6)返回成功
注  意:  ①因为我们 判断nowNode是否结束, 是直接判断 nowNode ?= L, 所以初始不能 nowNode = L
返回值:  bool:插入是否成功? true:false
**************************************************/
bool InsertElement_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType insert_value)
{int counter;bool result;singleLinkList_Cyclic *nowNode,*newNode;nowNode = L;//(3)if(specific_locate == 1)//只插入到第一个节点(头插法){newNode = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));newNode->data = insert_value;newNode->next = L->next;L->next = newNode;result = true;}else{nowNode = L->next;counter = 1;          //因为nowNode最低指向 L->next,所以只能插如第2~n个位置while(counter < (specific_locate-1) && nowNode != L)//①找到第(specific_locate-1)个元素{counter++;nowNode = nowNode->next;}if(nowNode == L){result = false;printf("Position overrun!\n");}else{newNode = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));newNode->data = insert_value;newNode->next = nowNode->next;nowNode->next = newNode;result = true;}}return result;}/**************************************************
(11)函数名: Delete_SpecificLocate_CyclicList
功  能: 删除特定位置的节点值
参  数: (1)singleLinkList_Cyclic *&L: 要删除节点的循环单链表(2)int specific_locate: 要删除的特定位置(3)ElemType &delete_value: 删除节点的值
注  意:   ① 删除节点,至少需要一个节点②后面删除的是 2~n个节点
思  路: (1)范围控制(注意事项)(2)找到要删除的节点的前一个位置,(3)删除节点
返回值:   无
**************************************************/
bool Delete_SpecificLocate_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType &delete_value)
{int counter;bool result;singleLinkList_Cyclic *nowNode,*deleteNode;nowNode = L;if(L->next == L){result = false;}elseif(specific_locate == 1)//①至少有一个节点{deleteNode = L->next;   //存储要删除的节点delete_value = deleteNode->data;L->next = deleteNode->next;free(deleteNode);result =  true;}else{//②后面就是删除第 2~n个节点nowNode = L->next;      //此时我们只能删除nowNode后面的节点,也就是第二个节点counter = 1;while(counter < (specific_locate-1) && nowNode != L)   //还是要找到第 specific_locate-1 个节点{counter++;nowNode = nowNode->next;}if(nowNode == L){result = false;}else{deleteNode = nowNode->next;delete_value = deleteNode->data;nowNode->next = deleteNode->next;free(deleteNode);result = true;}}return result;}

4. main.cpp测试函数

#include <stdio.h>#include "Cyclic_singleLinkList.h"int main()
{singleLinkList_Cyclic *L1,*L2;ElemType elem;ElemType A[] = {1,2,3,4,5,6,7,8};ElemType B[] = {11,22,33,44,55,66,77,88};Create_CyclicList_Head(L1,A,8);printf("头插法建立单链表 L1\n");Display_CyclicList(L1);Create_CyclicList_Tail(L2,B,8);printf("\n尾插法建立单链表 L2\n");Display_CyclicList(L2);printf("\n清空初始化L1\n");Init_CyclicList(L1);printf("\n判断L1,是否为空:\n");if(Empty_CyclicList(L1)){printf("L1被清空弹夹了!\n");}printf("\n求L2此时的长度: %d\n",Length_CyclicList(L2));elem = 66;printf("\n%d在L2中是第%d个元素\n",elem,SpecificValue_Location_CyclicList(L2,elem));elem = 88;if(SpecificLocate_Value_CyclicList(L2,8,elem)){printf("\nL2中第8个元素是%d\n",elem);}elem = 99;if(InsertElement_CyclicList(L1,1,elem)){printf("\n%d插入L1成功了\n",elem);}printf("\n%d在L1中是第%d个元素\n",elem,SpecificValue_Location_CyclicList(L1,elem));return 0;
}

5. 运行展示:

V2.0

v1.0 bug复现

调用函数(11)

运行错误结果:

原因分析:

由于我们删除的是链表节点,所以查找的是 删除节点的前一个节点, 这个节点我们已经做了 非法判断,

但是 当删除的前一个节点为链表的最后一个节点时, 我们就无法找到要删除的节点, 

所以我们要再做一次  删除节点的存在判断

再次运行,即可解决卡极限bug:

1.主要功能

//(1)头插法建立循环单链表
void Create_CyclicList_Head(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number);
//(2)尾插法建立单链表
void Create_CyclicList_Tail(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number);
//(3)输出循环单链表
void Display_CyclicList(singleLinkList_Cyclic *L);
//(4)初始化循环单链表
void Init_CyclicList(singleLinkList_Cyclic *&L);
//(5)销毁循环单链表
void Destroy_CyclicList(singleLinkList_Cyclic *&L);
//(6)判断循环单链表是否为空
bool  Empty_CyclicList(singleLinkList_Cyclic *L);
//(7)求循环单链表数据元素个数(不包括头结点)
int Length_CyclicList(singleLinkList_Cyclic *L);//(8) 查找特定元素值,在循环单链表中的位置
int SpecificValue_Location_CyclicList(singleLinkList_Cyclic *L, ElemType specific_value);//(9) 取出循环单链表中 特定位置的元素值
bool SpecificLocate_Value_CyclicList(singleLinkList_Cyclic *L, int specific_locate,ElemType &get_value);//(10) 把特定的节点值, 插入到循环单链表特定位置
bool InsertElement_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType insert_value);
//(11) 删除特定位置的节点值
bool Delete_SpecificLocate_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType &delete_value);

2. 循环链表头文件

Cyclic_singleLinkList.h 

#ifndef CYCLIC_SINGLELINKLIST_H_INCLUDE
#define CYCLIC_SINGLELINKLIST_H_INCLUDE#include "stdio.h"
#include "malloc.h"//循环单链表基本运算函数
typedef int ElemType;
typedef struct Cyclic_Node
{ElemType data;struct Cyclic_Node *next;
}singleLinkList_Cyclic;//(1)头插法建立循环单链表
void Create_CyclicList_Head(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number);
//(2)尾插法建立单链表
void Create_CyclicList_Tail(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number);
//(3)输出循环单链表
void Display_CyclicList(singleLinkList_Cyclic *L);
//(4)初始化循环单链表
void Init_CyclicList(singleLinkList_Cyclic *&L);
//(5)销毁循环单链表
void Destroy_CyclicList(singleLinkList_Cyclic *&L);
//(6)判断循环单链表是否为空
bool  Empty_CyclicList(singleLinkList_Cyclic *L);
//(7)求循环单链表数据元素个数(不包括头结点)
int Length_CyclicList(singleLinkList_Cyclic *L);//(8) 查找特定元素值,在循环单链表中的位置
int SpecificValue_Location_CyclicList(singleLinkList_Cyclic *L, ElemType specific_value);//(9) 取出循环单链表中 特定位置的元素值
bool SpecificLocate_Value_CyclicList(singleLinkList_Cyclic *L, int specific_locate,ElemType &get_value);//(10) 把特定的节点值, 插入到循环单链表特定位置
bool InsertElement_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType insert_value);
//(11) 删除特定位置的节点值
bool Delete_SpecificLocate_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType &delete_value);#endif     //CYCLI_SINGLELINKLIST_H_INCLUDE

3. 循环链表库函数

Cyclic_singleLinkList.cpp

#include "Cyclic_singleLinkList.h"/**************************************************
(1)函数名: Create_CyclicList_Head
功  能: 头插法建立循环单链表
参  数: (1)singleLinkList_Cyclic *&L: 要建立并传回去的循环单链表指针地址(2)ElemType Array_used[]: 要使用的数组数据(3)int Array_number: 数组的长度
注 意: ①我们是按照单链表方法建立,最后找到尾指针,再形成闭环
思 路:  (1)创建头结点(2)头结点置空(3)根据数据创建新节点,并利用头插法插入(4)查找尾结点(5)形成闭环
返回值: 无
**************************************************/
void Create_CyclicList_Head(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number)
{int counter;singleLinkList_Cyclic *newnode,*tailnode;L = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic)); //创建头结点L->next = NULL;for(counter = 0; counter < Array_number; counter++){newnode = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));  //创建新节点newnode->data = Array_used[counter];newnode->next = L->next;         //将newnode插在原开始结点之前,头结点之后L->next = newnode;}tailnode = L;while(tailnode->next != NULL) //①查找尾结点, 从而将其指向头结点{tailnode = tailnode->next;}tailnode->next = L;         // 形成闭环}/**************************************************
(2)函数名: Create_CyclicList_Tail
功  能: 尾插法建立单链表
参  数: (1)singleLinkList_Cyclic *&L: 要建立并传回去的循环单链表指针地址(2)ElemType Array_used[]: 要使用的数组数据(3)int Array_number: 数组的长度
注 意:   我们是按照单链表建立的方法进行建立,最后尾指针指向头结点即可
思 路:   (1)定义新节点,尾指针节点,数组遍历序号(2)创建头结点,并置空后继指针(3)按照数组顺序,新建节点,并利用尾插法插入链表尾部(4)插入完成,尾指针指向头结点
返回值:   无
**************************************************/
void Create_CyclicList_Tail(singleLinkList_Cyclic *&L,ElemType Array_used[],int Array_number)
{int counter;singleLinkList_Cyclic *newNode,*tailNode;L = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));L->next = NULL;tailNode = L;for(counter = 0; counter < Array_number; counter++){newNode = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));newNode->data = Array_used[counter];tailNode->next = newNode;tailNode = newNode;}tailNode->next = L;}/**************************************************
(3)函数名: Display_CyclicList
功  能: 输出展示循环单链表
参  数:(1)singleLinkList_Cyclic *L:要展示的循环单链表
注 意:①因为是循环单链表,所以结束条件是, 指针指向头结点
思 路:  (1)定义遍历节点(2)判断是否为空(L == L->next)(3)从数据节点开始遍历输出(4)不结束接着遍历输出
返回值: 无
**************************************************/
void Display_CyclicList(singleLinkList_Cyclic *L)
{singleLinkList_Cyclic *showNode;showNode = L->next;if(showNode == L){printf("hey, it is Empty!");     //为空,无法输出}while(showNode != L)//①{printf("%d",showNode->data);printf(" ");showNode = showNode->next;}printf("\n");
}/**************************************************
(4)函数名: Init_CyclicList
功  能: 初始化循环单链表
参  数: singleLinkList_Cyclic *&L:要初始化的循环单链表指针地址
返回值: 无
**************************************************/void Init_CyclicList(singleLinkList_Cyclic *&L)
{L = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));L->next = L;    //初始化头结点指向自己
}/**************************************************
(5)函数名: Destroy_CyclicList
功  能: 释放循环单链表的节点空间,
参  数: singleLinkList_Cyclic *&L:要销毁的循环单链表
注 意: ①防止野指针被函数利用后, 飘飞②防止遍历指针信息被删除后,找不到后继信息③循环单链表,结束条件是 尾指针指向头结点
思 路:   (1)定义遍历指针和后继指针(2)规划好nowNode和backNode关系(3) nowNode遍历删除,backNode后移,直到backNode == L,退出(4)接着释放nowNode,并且防止野指针飘飞,①返回值:  无
**************************************************/
void Destroy_CyclicList(singleLinkList_Cyclic *&L)
{singleLinkList_Cyclic *nowNode;singleLinkList_Cyclic *backNode;    //②nowNode = L;backNode = nowNode->next;while(backNode != L)        //③{free(nowNode);nowNode = backNode;backNode = backNode->next;}free(nowNode);L->next = L;    //①
}/**************************************************
(6)函数名: Empty_CyclicList
功  能: 判断循环单链表是否为空
参  数: singleLinkList_Cyclic *L:要参与判断的循环单链表
返回值: bool:是否为空? true:false
**************************************************/
bool  Empty_CyclicList(singleLinkList_Cyclic *L)
{return (L->next == L);
}
/**************************************************
(7)函数名: Length_CyclicList
功  能: 求循环单链表数据元素个数(不包括头结点)
参  数: singleLinkList_Cyclic *L :要参与计算的循环单链表
注  意: ① 结束条件:尾指针指向头结点
返回值:  int: 循环单链表数据元素个数
**************************************************/
int Length_CyclicList(singleLinkList_Cyclic *L)
{int counter = 0;singleLinkList_Cyclic *nowNode = L;while(nowNode->next != L)     //①{counter++;nowNode = nowNode->next;}return counter;
}
/**************************************************
(8)函数名:SpecificValue_Location_CyclicList
功  能:找特定元素值,在循环单链表中的位置
参  数:(1)singleLinkList_Cyclic *L:  需要查找的循环单链表(2)ElemType specific_value:   要查找的元素值
注 意: ① 从 L->next开始,即第一个数据元素开始查找,其位置counter伴随②跳出有两种情况:1,找到 2,超范围指向头结点
返回值: int: 返回特定元素值的 位置(0:未找到 , 1~n: 找到)
**************************************************/
int SpecificValue_Location_CyclicList(singleLinkList_Cyclic *L, ElemType specific_value)
{int counter = 1;singleLinkList_Cyclic *nowNode = L->next;   //①while((nowNode != L) && (nowNode->data != specific_value)){counter++;nowNode = nowNode->next;}if(nowNode == L)         //②如果指向头结点,则未找到{return 0;}else{return counter;}}
/**************************************************
(9)函数名:SpecificLocate_Value_CyclicList
功  能:取出循环单链表中 特定位置的元素值
参  数:(1)singleLinkList_Cyclic *L: 要进行遍历查找的循环单链表(2)int specific_locate: 要定位的特定位置(3)ElemType &value: 传回对应的节点数据
注  意:①循环链表,超范围条件是nowNode = L,如果从头开始,nowNode = L,counter = 0,就会默认到头所以从第 L->next开始算,② 从① 开始算的前提是,L有后继节点,也就是L不是空表③ L不是空表, 但是所给位置,超出循环链表长度,仍返回错误④ ②和③其实可以归为一类,都是长度不足,但是为了做区分, 分开了
思  路:(1)定义当前节点和位置序号  (2)从第一个数据节点开始(3) 空表直接跳出          (4)通过对比位置信息 和 检测 节点循环链表是否超范围(5)传回特定位置信息  或者 超范围标志false返回值:  bool: 是否找到特定位置,并传回节点数据? true:false
**************************************************/
bool SpecificLocate_Value_CyclicList(singleLinkList_Cyclic *L, int specific_locate,ElemType &get_value)
{int counter = 1;bool result;singleLinkList_Cyclic *nowNode;nowNode = L->next;     //①if(nowNode == L)     //②{result = false;   //循环链表为空表,跳出}else{while(counter < specific_locate && nowNode != L){counter++;nowNode = nowNode->next;}if(nowNode == L)    //③{result = false;        //位置还未到,链表到头了,长度不足}else{get_value = nowNode->data;result = true;}}return result;
}/**************************************************
(10)函数名: InsertElement_CyclicList
功  能:特定的节点值,插入到循环单链表特定位置
参  数:(1)singleLinkList_Cyclic *&L:要插入的循环单链表(2)int specific_locate: 要插入的特定位置(3)ElemType insert_value: 要插入的特定值思  路: (1)定义遍历节点nowNode,新节点newNode   (2)从头开始遍历,到特定位置(3) 不管是否为空表,第一个位置都可以插入成功,单独摘出(4)  后续遍历nowNode从 nowNode = L->next开始,只能插入到第2~n个位置(5)  查找第(specific_locate-1 )个位置{是否超范围? true:false},将新节点插入其后(6)返回成功
注  意:  ①因为我们 判断nowNode是否结束, 是直接判断 nowNode ?= L, 所以初始不能 nowNode = L
返回值:  bool:插入是否成功? true:false
**************************************************/
bool InsertElement_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType insert_value)
{int counter;bool result;singleLinkList_Cyclic *nowNode,*newNode;nowNode = L;//(3)if(specific_locate == 1)//只插入到第一个节点(头插法){newNode = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));newNode->data = insert_value;newNode->next = L->next;L->next = newNode;result = true;}else{nowNode = L->next;counter = 1;          //因为nowNode最低指向 L->next,所以只能插如第2~n个位置while(counter < (specific_locate-1) && nowNode != L)//①找到第(specific_locate-1)个元素{counter++;nowNode = nowNode->next;}if(nowNode == L){result = false;printf("Position overrun!\n");}else{newNode = (singleLinkList_Cyclic*)malloc(sizeof(singleLinkList_Cyclic));newNode->data = insert_value;newNode->next = nowNode->next;nowNode->next = newNode;result = true;}}return result;}/**************************************************
(11)函数名: Delete_SpecificLocate_CyclicList
功  能: 删除特定位置的节点值
参  数: (1)singleLinkList_Cyclic *&L: 要删除节点的循环单链表(2)int specific_locate: 要删除的特定位置(3)ElemType &delete_value: 删除节点的值
注  意:   ① 删除节点,至少需要一个节点②后面删除的是 2~n个节点③由于找到删除节点的前一个节点(specific_locate-1),前一个在范围内,但删除节点不一定
思  路: (1)范围控制(注意事项)(2)找到要删除的节点的前一个位置,(3)删除节点
返回值:   无
**************************************************/
bool Delete_SpecificLocate_CyclicList(singleLinkList_Cyclic *&L, int specific_locate, ElemType &delete_value)
{int counter;bool result;singleLinkList_Cyclic *nowNode,*deleteNode;nowNode = L;if(L->next == L){printf("The single linked list is empty and cannot be deleted!\n");result = false;}elseif(specific_locate == 1)//①至少有一个节点{deleteNode = L->next;   //存储要删除的节点delete_value = deleteNode->data;L->next = deleteNode->next;free(deleteNode);result =  true;}else{//②后面就是删除第 2~n个节点nowNode = L->next;      //此时我们只能删除nowNode后面的节点,也就是第二个节点counter = 1;while(counter < (specific_locate-1) && nowNode != L)   //还是要找到第 specific_locate-1 个节点{counter++;nowNode = nowNode->next;}if(nowNode == L){printf("(1)Single linked list deletion out of range!\n");result = false;}else{deleteNode = nowNode->next;if(deleteNode == L) //{printf("(2)Single linked list deletion out of range!\n");result = false;}else{delete_value = deleteNode->data;nowNode->next = deleteNode->next;free(deleteNode);result = true;}}}return result;}

4. main.cpp测试函数

#include <stdio.h>#include "Cyclic_singleLinkList.h"int main()
{singleLinkList_Cyclic *L1,*L2;ElemType elem;ElemType A[] = {1,2,3,4,5,6,7,8};ElemType B[] = {11,22,33,44,55,66,77,88};Create_CyclicList_Head(L1,A,8);printf("头插法建立单链表 L1\n");Display_CyclicList(L1);Create_CyclicList_Tail(L2,B,8);printf("\n尾插法建立单链表 L2\n");Display_CyclicList(L2);if(Delete_SpecificLocate_CyclicList(L2,9,elem)){//v2.0 bug验证并修复printf("成功删除了%d\n",elem);}printf("\n清空初始化L1\n");Init_CyclicList(L1);printf("\n判断L1,是否为空:\n");if(Empty_CyclicList(L1)){printf("L1被清空弹夹了!\n");}printf("\n求L2此时的长度: %d\n",Length_CyclicList(L2));elem = 66;printf("\n%d在L2中是第%d个元素\n",elem,SpecificValue_Location_CyclicList(L2,elem));elem = 88;if(SpecificLocate_Value_CyclicList(L2,8,elem)){printf("\nL2中第8个元素是%d\n",elem);}elem = 99;if(InsertElement_CyclicList(L1,1,elem)){printf("\n%d插入L1成功了\n",elem);}printf("\n%d在L1中是第%d个元素\n",elem,SpecificValue_Location_CyclicList(L1,elem));return 0;
}

5. 运行展示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/811063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react17中配置webpack:使用@代表src目录

在vue的项目中可以使用表示src目录&#xff0c;使用该符号表示绝对路径&#xff0c;那么在react中想要使用怎么办呢&#xff1f; 在react中使用表示src目录是需要在webpack中配置的&#xff0c;在核心模块node_modules-》react-scripts-》config-》webpack.config.js中搜索找到…

【数据结构与算法】之8道顺序表与链表典型编程题心决!

个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 目录 1、顺序表 1.1 合并两个有序数组 1.2 原地移除数组中所有的元素va…

51-37 由浅入深理解 Stable Diffusion 3

2024年3月5日&#xff0c;Stability AI公开Stable Diffusion 3论文&#xff0c;Scaling Rectified Flow Transformers for High-Resolution Image Synthesis。公司像往常一样承诺后续将开源代码&#xff0c;开源之光&#xff01;&#xff01;&#xff01; 在LDW潜在扩散模型论文…

​​​​网络编程学习探索系列之——广播原理剖析

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的网络编程系列之广播原理剖析&#xff0c;在这篇文章中&#xff0c; 你将会学习到如何在网络编程中利用广播来与局域网内加入某个特定广播组的主机&#xff01; 希望这篇文章能对你有所帮助&#xff0c;大家要是觉得我写…

Leetcode算法训练日记 | day24

一、组合问题 1.题目 Leetcode&#xff1a;第 77 题 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4…

福建单航次最大批量汽车“出海”

3月12日这一天&#xff0c;在福州海关的严密监管下&#xff0c;共有4000辆上汽名爵品牌的汽车被高效有序地装载到“安吉智慧”号滚装船上&#xff0c;这批车辆即将启程前往荷兰、埃及、英国等多个海外市场。在这批出口汽车中&#xff0c;新能源车型占据了显著的比例&#xff0c…

OceanMind海睿思助力企业“数据入表”经济利益流入与生命周期管理

通过多年信息系统的建设与应用&#xff0c;企业积累了大量的数据。同时随着时间的推进&#xff0c;数据规模正以加速度快速增长。从国家到企业&#xff0c;都越来越关注所拥有的数据资源及其蕴含的深厚价值。很多企业已经逐渐认知到数据是重要的战略资源&#xff0c;数据资产化…

游标的定义和类型

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 游标的基本概念 游标从字面上理解为游动的光标&#xff0c;可以使用 Excel 表格来想象游标的作用&#xff0c;游标指向每一行&#xff0c;通过游标访问每行数据。 在 Orac…

2024/4/5—力扣—字符串相乘

代码实现&#xff1a; 方法一&#xff1a;常规解法——超出整数表示范围 long long char_to_num(char *str) {long long num 0;for (int i 0; i < strlen(str); i) {num num * 10 (str[i] - 0);}return num; }char* multiply(char *num1, char *num2) {long long a cha…

Git基础操作及其分支管理

目录 一、git的用处&#xff1f; 1.1 git也不是银弹 二、安装git 三、git基础操作 3.1 创建git本地仓库 3.2 配置Git 3.3 认识工作区、暂存区、版本库 3.4 添加文件 3.5 Git文件目录 3.6 版本回退 3.7 撤销修改 3.7.1 对于工作区的代码&#xff0c;还没有进行add操作…

学习51单片机必备:从电子基础到编程技巧全解析

学习51单片机需要掌握一系列的基础知识和技能&#xff0c;以下是一些主要的学习内容&#xff1a; 电子基础知识 了解基本的电子元件和电路原理是学习单片机的基础。这有助于理解单片机如何与外围设备交互以及如何设计电路。 数字逻辑 理解数字逻辑和布尔代数&#xff0c;对于编…

Redis性能管理和集群的三种模式(二)

一、Redis集群模式 1.1 redis的定义 redis 集群 是一个提供高性能、高可用、数据分片、故障转移特性的分布式数据解决方案 1.2 redis的功能 数据分片&#xff1a;redis cluster 实现了数据自动分片&#xff0c;每个节点都会保存一份数据故障转移&#xff1a;若个某个节点发生故…

探索柔性负荷在综合能源系统中的优化调度策略

柔性负荷&#xff0c;指的是那些可以根据系统需求和市场信号调整其使用模式的负荷。它们包括可平移负荷、可转移负荷和可削减负荷。这些负荷的灵活性为IES&#xff08; Integrated Energy System, 综合能源系统&#xff09;提供了额外的调节能力&#xff0c;有助于平衡供需、提…

MyBatis实例更新

MyBatis具体 准备工作 预编译SQL 新增 更新 查询 //查询员工Select("select * from emp where id #{id}")public Emp getById(Integer id);//方案一:给字段起别名&#xff0c;让别名与实体类属性一致Select("select id,username,password,name,gender,image,j…

DataX案例,MongoDB数据导入HDFS与MySQL

【尚硅谷】Alibaba开源数据同步工具DataX技术教程_哔哩哔哩_bilibili 目录 1、MongoDB 1.1、MongoDB介绍 1.2、MongoDB基本概念解析 1.3、MongoDB中的数据存储结构 1.4、MongoDB启动服务 1.5、MongoDB小案例 2、DataX导入导出案例 2.1、读取MongoDB的数据导入到HDFS 2…

Failed to load dll

Unity运行时提示 dll 加载失败 Plugins: Failed to load ‘Assets/Plugins/xxx.dll’ because one or more of its dependencies could not be loaded. 使用 Dependency Walker 查看这个 dll 引用&#xff0c;一推引用丢失 最后确认是 C 组件缺失 打开 Visual Studio Install…

Java基础入门--第十一章--JDBC(Java Database Connection)Java数据库连接

JDBC 11.1 什么是JDBC11.1.1 JDBC概述11.1.2 JDBC驱动程序 11.2 JDBC的常用API11.3 JDBC编程11.3.1 JDBC 编程步骤11.3.2 实现第一个JDBC程序 我的MySQL的root密码: root 11.1 什么是JDBC 11.1.1 JDBC概述 JDBC的全称是Java数据库连接&#xff08;Java Database Connectivit…

光威神策PRO PCIe 5.0 SSD发布,国产固态硬盘进入10G俱乐部

全球半导体供应链的紧张局势和闪存资源的短缺让许多行业都面临着不小的压力 &#xff0c; 连带的也让消费者难以获取物美价廉的闪存产品 。但是&#xff0c;总有一些企业能够逆流而上&#xff0c; 像是 光威科技这家国产存储品牌&#xff0c; 最近就给国内消费者 带来了一个惊喜…

【JAVA基础篇教学】第六篇:Java异常处理

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第五篇&#xff1a; Java异常处理。 异常处理是Java编程中重要的一部分&#xff0c;它允许开发人员在程序运行时检测和处理各种错误情况&#xff0c;以保证程序的稳定性和可靠性。在Java中&#xff0c;异常被表示为对象&am…

【Kafka】Zookeeper集群 + Kafka集群

Zookeeper 概述 Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目。 Zookeeper 工作机制★★★ Zookeeper从设计模式角度来理解&#xff1a; 1&#xff09;是一个基于观察者模式设计的分布式服务管理框架&#xff1b; 它负责存储和管理大家都关…