3-循环链表

循环链表没有头结点 只有头指针,由头指针指向循环链表中的任意一个结点(指向谁 谁就是头节点)
在这里插入图片描述
多用于双向循环链表:
头结点的前驱指针指向最后一个结点
尾结点的后继指针指向头节点
一般都会把头结点写上

main.cpp

#include "pch.h"
#include <iostream>
#include"CirList.h"
int main()
{
        CirList list;
        Init_List(&list);
        Insert_ListHead(&list, 10);
        Insert_ListHead(&list, 20);
        Show(list);
        Insert_ListTail(&list, 30);
        Show(list);
}

CirList.cpp

// Cirlist.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include"CirList.h"
#include<assert.h>
bool IsEmpty(CirList list)//不修改这个指针所以不用传二级指针--?????
{
        return list == NULL;//
}
static int Length(CirList list)
{
        if (list==NULL) return 0;
        CirList p = list;
        int count = 0;
        while (p->next != list)
        {
               count++;
               p = p->next;
        }
        return count + 1;
}
bool Init_List(CirList *list)//要修改这个指针的话就传二级指针
{//因为定义的是CirList list 指针对象 所以要修改的话要传* 如果定义的Node对象 则传引用
        assert(list != NULL);
        if (list == NULL)
        {
               return false;
        }
        *list = NULL;//将main函数的list指向空
        return true;
}
static CirList ApplyNode(ElemType val, CirList next)
{//申请节点的函数不光传进来节点内存的值 还有要插入的节点的位置
        CirList s = (CirList)malloc(sizeof(CNode));//先申请一个节点的空间
        assert(NULL != s);
        s->data = val;
        if (next)
        {
               s->next = next;
        }
        else
               s->next = s;//如果传入的是NULL 说明链表为空 那这个时候循环链表内只有一个节点 自然是自己指向自己
        return s;
        
}
bool Insert_ListPos(CirList *list, ElemType val, int pos)
{
        if (pos == 0)
        {
               return Insert_ListHead(list, val);
        }
        if (pos % Length(*list) == 0)
        {
               return Insert_ListTail(list, val);
        }
        pos %= Length(*list);
        CirList p = *list;
        while (pos > 1)
        {
               p = p->next;
               pos--;
        }
        p->next = ApplyNode(val, p->next);
        return true;
}
bool Insert_ListHead(CirList *list, ElemType val)
{
        Insert_ListTail(list, val);//先在尾部插入要插入的值
        CirList p = *list;
        while (p->next != *list)//一直循环到p到了头指针的前一个
        {
               p = p->next;
        }
        *list = p;//头指针指向p 也就是循环链表的最后一个(插入的那个)
        //实现头插
        return true;
}
bool Insert_ListTail(CirList *list, ElemType val)
{
        if (IsEmpty(*list))
        {
               *list = ApplyNode(val, NULL);
               return true;
        }
        CirList p = *list;
        while (p->next != *list)//一直循环到p到了头指针的前一个
        {
               p = p->next;
        }
        p->next = ApplyNode(val, p->next);//要插入的值和位置都传进去
}
void Show(CirList list)
{
        if (list == NULL)
        {
               return;
        }
        CirList p = list;//因为不想改变链表 所以不用传地址
        while (p->next != list)
        {
               printf("%d", p->data);
               p = p->next;
        }
        printf("%d  ", p->data);//因为还有最后一个要输出
        printf("\n");
}
bool Delete_ListHead(CirList *list)
{
        if (IsEmpty(*list))
        {
               return false;
        }
        int len = Length(*list);
        CirList p = *list;
        while (p->next != *list)
        {
               printf("%d", p->data);
               p = p->next;
        }
        CirList q = *list;//q现在指向头指针
        *list = q->next;//头指针现在往下移动了一为
        p->next = *list;//最后一位绕过q直接到了头指针 达到删除
        free(q);
        if (len == 1)
               *list = NULL;
        return true;
}
bool Delete_ListPos(CirList *list, int pos)
{
        if (pos == 0 || pos % Length(*list) == 0)
        {
               return Delete_ListHead(list);
        }
        int len = Length(*list);
        CirList p = *list;
        while (pos > 1)
        {
               p = p->next;
               pos--;
        }
        CirList q = p->next;
        p->next = q->next;
        free(q);
        if (len == 1)
               *list = NULL;
        return true;
}
bool Delete_ListTail(CirList *list)
{
        return Delete_ListPos(list, Length(*list) - 1);
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门提示:
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

CirList.h

#pragma once
typedef int ElemType;
typedef struct _Cir
{
        ElemType data;
        struct _Cir *next;
}CNode, *CirList;
///////////////////////////////
// 必须声明传递二级指针的函数:  初始化   插入   删除   清空   销毁
//////////////////////////////
bool Init_List(CirList *list);//初始化 这里的list是个二级指针
bool IsEmpty(CirList list);
bool Insert_ListHead(CirList *list, ElemType val);
bool Insert_ListTail(CirList *list, ElemType val);
bool Insert_ListPos(CirList *list, ElemType val,int pos);
void Show(CirList list);
bool Delete_ListHead(CirList *list);
bool Delete_ListTail(CirList *list);
bool Delete_ListPos(CirList *list, int pos);
发布了82 篇原创文章 · 获赞 7 · 访问量 4202

猜你喜欢

转载自blog.csdn.net/sunshine612/article/details/104701263