循环单链表算法库

学习贺老师数据结构

数据结构之自建算法库——循环单链表_循环单链表 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;
    }
    else
    if(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;
    }
    else
    if(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.mfbz.cn/a/538249.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Blender2.83 下载地址及安装教程

Blender是一款开源的3D计算机图形软件&#xff0c;广泛应用于动画制作、游戏开发、建模、渲染等领域。它提供了一套强大的工具和功能&#xff0c;让用户能够进行三维建模、动画制作和视觉效果的创作。 Blender支持多种文件格式的导入和导出&#xff0c;使用户能够与其他软件进…

【Linux源码学习】(一)源码下载、解压说明

目录 一、Linux源码下载地址 二、使用7z解压 一、Linux源码下载地址 官网下载&#xff1a;The Linux Kernel Archives 我们可以到这个地址下载各种版本的压缩包&#xff1a;即上图对应的http网址。 Index of /pub/ 选择Linux 找内核代码 这里直接选择最新的6.x 然后往下翻&…

《猎灵online》游戏完整源码(源码+客户端+服务端+文档+工具),云盘下载

《猎灵》是一款由国内知名开发运营开发的大型3D魔幻网游&#xff0c;《猎灵》研发团队突破诸多瓶颈&#xff0c;首创“全自由无限制PK”&#xff0c;让玩家拒绝无意义等待&#xff0c;自由作战不受任何束缚&#xff0c;真正的实现想战就战&#xff0c;游戏创建了六界神魔乱斗的…

单调栈用法

文章目录 1. 单调栈1.1 理解单调栈&#xff08;模板&#xff09;1.2 每日温度1.3 子数组的最小值之和1.4 柱状图中最大的矩形1.5 最大矩形1.6 最大宽度坡1.7 去除重复字母 1. 单调栈 单调栈经典的用法&#xff1a; 对每个位置都求&#xff1a; 当前位置的左侧比当前位置的数…

UDP网络程序

上一章中&#xff0c;我们介绍了socket&#xff0c;以及TCP/UDP协议。这一章带大家实现几个UDP协议的网络服务。我们需要一个 服务端和一个客户端。 1.服务端实现 1.1socket函数 #include <sys/types.h> #include <sys/socket.h>int socket(int domain, in…

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

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

【 书生·浦语大模型实战营】作业(三):“茴香豆” 搭建你的RAG 智能助理

【 书生浦语大模型实战营】学习笔记&#xff08;三&#xff09;&#xff1a;“茴香豆” 搭建你的RAG 智能助理作业 &#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI…

JVM参数列表

-client :设置JVM使用client模式,特点启动较快(神机不明显(I5/8G/SSD)) -server :设置JVM使用server模式。64位JDK默认启动该模式 -agentlib:libname[options] :用于加载本地的lib -agentlib:hprof :用于获取JVM的运行情况 -agentpath:pathnamep[options] :加载制定路径的本…

PHP01——php快速入门 之 使用phpstudy快速搭建PHP环境

PHP01——php快速入门 之 使用phpstudy快速搭建PHP环境 0. 前言1. 下载小皮面板1.1 下载phpstudy&#xff08;小皮面板&#xff09;1.2 启动、简单访问1.2.1 启动Apache1.2.2 访问1.2.3 访问自定义文件或页面 2. 创建网站2.1 创建网站2.2 可能遇到的问题2.2.1 hosts权限问题&am…

极海APM32电机驱动板记录(二)

文章目录 1、解除写保护2、极海驱动板资源概述3、新建工程4、点灯5、嘀嗒定时器6、中断7、串口打印8、adc读取9、i2c尝试10、定时器测试11、电机驱动pwm测试 上一篇文章算是简单了解了一下极海的板子开发环境吧&#xff0c;结果前几天板子来了&#xff0c;然后发现一个大bug&am…

力扣题目 19:删除链表的倒数第N个节点 【python】

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a; 码上找工作http://t.csdnimg.cn/Q59WX 作者专栏每日更新&#xff1a; LeetCod…

Qt-绘制多边形、椭圆、多条直线

1、说明 所有的绘图操作是在绘图事件中进行。mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECTpublic:MainWi…

C++ 类和对象(一)

目录 0.前言 1.面向过程&面向对象 1.1面向过程编程&#xff08;PP&#xff09; 1.2面向对象编程&#xff08;OOP&#xff09; 1.3从C到C 2.类的引入 2.1C语言中的结构体 2.2C中类的引入 2.3结构体与类的区别 2.4为什么引入类 3.类的定义 3.1声明与定义不分离 …

【Java探索之旅】从输入输出到猜数字游戏

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、输入输出1.1 输出到控制台1.2 从键盘输入 二、猜数字游戏2.1 所需知识&#xff1a…

【动态规划】【01背包】Leetcode 1049. 最后一块石头的重量 II

【动态规划】【01背包】Leetcode 1049. 最后一块石头的重量 II 解法 ---------------&#x1f388;&#x1f388;题目链接&#x1f388;&#x1f388;------------------- 解法 &#x1f612;: 我的代码实现> 动规五部曲 ✒️确定dp数组以及下标的含义 dp[j]表示容量为…

Learn SRP 01

学习链接&#xff1a;Custom Render Pipeline (catlikecoding.com) 使用Unity版本&#xff1a;Unity 2022.3.5f1 1.A new Render Pipeline 1.1Project Setup 创建一个默认的3D项目&#xff0c;项目打开后可以到默认的包管理器删掉所有不需要的包&#xff0c;我们只使用Unit…

陆面、生态、水文模拟与多源遥感数据同化

原文链接&#xff1a;陆面、生态、水文模拟与多源遥感数据同化https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601198&idx6&sn51b9b26b75c9df1f11dcb9a187878261&chksmfa820dc9cdf584df9ac3b997c767d63fef263d79d30238a6523db94f68aec621e1f91df85f6…

算法——字符串

T04BF &#x1f44b;热门专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享字符串相关算法 如果有不足的或者错误的请您指出! 目录 1.最长公共前缀1.1解析1.2题解 2.最长回文子串2.1解析2.2题解 3.二级制求和3.1解析3.2题解 4.字符串相乘4.1解析4.2…

【环境变量】常见的环境变量 | 相关指令 | 环境变量系统程序的结合理解 | 环境变量表 | 本地变量环境变量 | 外部命令内建命令

目录 常见的环境变量 HOME PWD SHELL HISTSIZE 环境变量相关的指令 echo&env export unset 本地变量 环境变量整体理解 程序现象_代码查看环境变量 ​整体理解 环境变量表 环境变量表的传递 环境变量表的查看 内建命令 少说废话&#x1f197; 每个用…

大型网站系统架构演化

大型网站质量属性优先级&#xff1a;高性能 高可用 可维护 应变 安全 一、单体架构 应用程序&#xff0c;数据库&#xff0c;文件等所有资源都在一台服务器上。 二、垂直架构 应用和数据分离&#xff0c;使用三台服务器&#xff1a;应用服务器、文件服务器、数据服务器 应用服…
最新文章