准挝 发表于 2025-8-1 01:39:29

2.单向循环链表的接口设计

/****************************************************************************
*
* file name: 2025-07-11_CircularLinkedList.c
* author   : 15515376695@163.com
* date   : 2025-07-11
* function : 该程序设计单向循环链表的接口
* note   : None
* CopyRight (c)   202515515376695@163.com   Right Reseverd
*
****************************************************************************/
//用户可以根据自己的需要进行修改所需的数据类型
typedef int DataType_t;
//构造单向循环链表的结点,链表中所有结点的数据类型应该是相同的
typedef struct CircularLinkedList
{
        DataType_t   data;         //记录结点的数据域
        struct CircularLinkedList*next; //记录结点的指针域
}CircLList_t;

//创建一个空单向循环链表,空链表应该有一个头结点,对链表进行初始化
CircLList_t * CircLList_Create(void)
{
        //1.使用calloc为单向循环链表的头结点从堆空间申请一块内存,对链表进行初始化
        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_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;
}

//单向循环链表头部插入
bool CircLList_HeadInsert(CircLList_t *Head,DataType_t data)
{
        //1.创建新的结点,并进行初始化
        CircLList_t *New = CircLList_NewNode(data);
        if (NULL == New)
        {
                printf("can not insert newnode\n");
                return false;
        }
        //2.判断链表是否为空,如果为空,直接插入
        if (Head->next == Head)
        {
                Head->next = New;
                New->next = New;
                return true;
        }
        //3.若链表为非空,则把新结点插入链表头部
        //先遍历找到尾结点地址
        CircLList_t *Phead = Head->next;//备份首结点地址
        //遍历寻找尾结点
        while(Phead->next != Head->next)
        {
                Phead = Phead->next;//        得到尾结点地址
        }
        //进行头插
        Phead->next = New;
        New->next = Head->next;
        Head->next = New;
        return true;
}
////单向循环链表尾部插入
bool CircLList_TailInsert(CircLList_t *Head,DataType_t data)
{
        CircLList_t *New = CircLList_NewNode(data);
        if (NULL == New)
        {
                printf("can not insert ner node\n");
                return false;
        }
        if (Head->next == Head)
        {
                Head->next = New;
                New->next = New;
                return true;
        }
        //若链表非空
        CircLList_t *Phead = Head->next;//备份首结点地址
        while(Phead->next != Head->next)
        {
                Phead = Phead->next;//        得到尾结点地址
        }
        //进行尾部插入
        Phead->next = New;
        New->next = Head->next;
        return true;
}
//向单向循环链表指定位置插入一个新的结点
bool CircLList_AppointInsert(CircLList_t *Head,DataType_t data,DataType_t DestVal)
{
        CircLList_t * New = CircLList_NewNode(data);
        if (NULL == New)
        {
                printf("can not insert ner node\n");
                return false;
        }
        if (Head->next == Head)
        {
                Head->next = New;
                New->next = New;
                return true;
        }
        //若链表非空
        CircLList_t * Phead = Head->next;
        while(Phead->data != DestVal)
        {
                Phead = Phead->next;
                if (Phead->next == Head->next && Phead->data != DestVal)
                {
                        printf("The DestVal doesn't exist! \n");
            return false;
                }
        }
        //找到目标节点
        New->next = Phead->next;
        Phead->next = New;
        return true;
       
}
//头删
bool CircLList_HeadDel(CircLList_t *Head)
{
        CircLList_t * Phead = Head->next;//备份首结点地址
        CircLList_t *Temp = Head->next;
        //判断链表是否为空
        if (Head->next == Head)
        {
                printf("CircLList is empty\n");
                return false;
        }
        //判断是否只含有首结点
        if (Head->next->next == Phead)
        {
                Head->next = Head;
                Phead->next = NULL;//首结点的指针域指向NULL,目的是防止野指针出现和内存泄漏
                free(Phead);//释放结点内存,防内存泄漏
                return true;
        }
        //如果为非空,且含有多个结点,
        //遍历找到尾结点
        while(Phead->next != Head->next)
        {
                Phead = Phead->next;
        }

        Phead->next = Head->next->next;
        Head->next = Head->next->next;
        Temp->next = NULL;
        free(Temp);
        return true;
}
//中删
bool CircLList_DestDel(CircLList_t *Head, DataType_t dest)
{
    // 检查头指针是否有效(防止空指针访问)
    if (Head == NULL)
    {
      printf("Error, Head pointer is NULL! \n");
      return false;
    }

    CircLList_t *Current = Head->next; // 指向首节点(若为空链表则指向头节点)
    CircLList_t *Prev = Head;          // 指向Current的前一个节点

    // 1. 判断链表是否为空(头节点的next指向自身)
    if (Head->next == Head)
    {
      printf("Error, CircularLinkList is empty! \n");
      return false;
    }

    // 2. 查找目标节点
    while (Current->data != dest)
    {
      Prev = Current;
      Current = Current->next;

      // 若遍历一圈回到首节点,说明未找到目标
      if (Current == Head->next)
      {
            printf("The target doesn't exist! \n");
            return false;
      }
    } // 退出循环时,Current指向目标节点,Prev指向其前驱

    // 3. 分情况删除目标节点
    // 3.1目标是首节点
    if (Current == Head->next)
    {
      // 3.1.1 链表只有一个节点(首节点的next指向头节点)
      if (Current->next == Head->next)
      {
            Head->next = Head; // 恢复为空链表
      }
      // 3.1.2 链表有多个节点
      else
      {
            // 找到尾节点(尾节点的next指向首节点)
            CircLList_t *Tail = Head->next;
            while (Tail->next != Head->next)
            {
                Tail = Tail->next;
            }
            // 尾节点指向新首节点,头节点更新新首节点
            Tail->next = Current->next;
            Head->next = Current->next;
      }
    }
    // 3.2 目标是尾节点(尾节点的next指向首节点)
    else if (Current->next == Head->next)
    {
      Prev->next = Head->next; // 前驱直接指向首节点
    }
    // 3.3 目标是中间节点
    else
    {
      Prev->next = Current->next; // 前驱指向目标的后继
    }

    // 释放目标节点内存
    free(Current);
    return true;
}
//尾删
bool CircLList_TailDel(CircLList_t *Head)
{
    CircLList_t *Current = Head->next;
    CircLList_t *Prev = Head;         

    // 1.判断单向循环链表是否为空
    if (Head->next == Head)
    {
      printf("Error,CircularLinkList is empty! \n");
      return false;
    }

    // 2.若单向循环链表非空
    // 若链表只有首结点
    if (Current->next == Head->next)
    {
      Head->next = Head; // 空链表状态
      Current->next = NULL;
      free(Current); // 防止内存泄漏
      return true;
    }
    // 若还有别的结点
    while (Current->next != Head->next) // 不断向下检查结点指针域
    {
      Prev = Current;
      Current = Current->next;         
    }
    // Current到达未尾结点 Prev为Current 的前一个位置
    Prev->next = Head->next; // 新尾结点链接首结点, 行成循环
    Current->next = NULL;
    free(Current); // 防止内存泄漏
    return true;
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 2.单向循环链表的接口设计