先写头文件clist.h
#pragma once
//循环链表结构体设计
typedef int ELEMTYPE;
typedef struct Clist
{
ELEMTYPE data; //数据域 存放数据
struct Clist* next;//指针域 存放下一个节点的地址(尾结点的next保存头结点的地址)
}Clist, *PClist;
//循环链表拥有的 可执行函数声明:
//初始化
void InitClist(struct Clist* plist);
//头插
bool Insert_head(PClist plist, ELEMTYPE val);
//尾插
bool Insert_tail(PClist plist, ELEMTYPE val);
//按位置插
bool Insert_pos(PClist plist, int pos, ELEMTYPE val);
//头删
bool Del_head(PClist plist);
//尾删
bool Del_tail(PClist plist);
//按位置删
bool Del_pos(PClist plist, int pos);
//按值删除
bool Del_val(PClist plist, ELEMTYPE val);
//查找(如果查找到,需要返回找到的这个节点的地址)
struct Clist* Search(struct Clist *plist, ELEMTYPE val);
//判空
bool IsEmpty(PClist plist);
//判满(循环链表不需要这个操作)
//获取长度
int Get_length(PClist plist);
//清空
void Clear(PClist plist);
//销毁1
void Destroy1(PClist plist);
//销毁2
void Destroy2(PClist plist);
//打印
void Show(struct Clist *plist);
再写dlist.cpp文件
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include "clist.h"
//循环链表里边很少出现NULL, nullptr
//初始化
void InitClist(struct Clist* plist)
{
//assert
//plist->data; // 数据域不处理
plist->next = plist;
}
//头插
bool Insert_head(PClist plist, ELEMTYPE val)
{
//assert
//1.购买新节点
struct Clist *pnewnode = (struct Clist*)malloc(1 * sizeof(struct Clist));
assert(pnewnode != NULL);
pnewnode->data = val;//购买的新节点 处理完毕
//2.找到插入位置 (头插 不用找)
//3.插入
pnewnode->next = plist->next;
plist->next = pnewnode;
return true;
}
//尾插
bool Insert_tail(PClist plist, ELEMTYPE val)
{
//assert
//1.购买新节点
struct Clist *pnewnode = (struct Clist*)malloc(1 * sizeof(struct Clist));
assert(pnewnode != NULL);
pnewnode->data = val;//购买的新节点 处理完毕
//2.找到插入位置(通过带前驱的for循环)
struct Clist *p = plist;
for(p; p->next!=plist; p=p->next);
//此时 for循环执行结束 p指向尾结点
//3.插入
pnewnode->next = p->next;
p->next = pnewnode;
return true;
}
//按位置插
bool Insert_pos(PClist plist, int pos, ELEMTYPE val)
{
assert(plist != NULL);
assert(pos>=0 && pos<=Get_length(plist));
//1.购买新节点
struct Clist *pnewnode = (struct Clist*)malloc(1 * sizeof(struct Clist));
assert(pnewnode != NULL);
pnewnode->data = val;//购买的新节点 处理完毕
//2.找到插入位置(通过带前驱的for循环)
struct Clist *p = plist;
for(int i=0; i<pos; i++)
{
p = p->next;
}
//此时 for循环执行结束 p指向待插入的合适位置
//3.插入
pnewnode->next = p->next;
p->next = pnewnode;
return true;
}
//头删
bool Del_head(PClist plist)
{
//assert
if(IsEmpty(plist))//不空 则至少存在一个有效值
{
return false;
}
//1.指针p指向待删除节点
struct Clist *p = plist->next;
//2.指针q指向待删除节点的前一个节点
//q 就是 头结点 这里就不再额外处理
//3.跨越指向
plist->next = p->next;
free(p);
return true;
}
//尾删
bool Del_tail(PClist plist)
{
//assert
if(IsEmpty(plist))//不空 则至少存在一个有效值
{
return false;
}
//1.指针p指向待删除节点(尾删的话,这里指向尾结点)
struct Clist *p = plist;
for(p; p->next!=plist; p=p->next);
//此时 for指向结束 代表着p指向尾结点
//2.指针q指向倒数第二个节点
struct Clist *q = plist;
for(q; q->next!=p; q=q->next);
//此时 for指向结束 代表着q指向p的上一个节点
//3.跨越指向
q->next = p->next;
free(p);
return true;
}
//按位置删
bool Del_pos(PClist plist, int pos)
{
assert(plist != NULL);
assert(pos>=0 && pos<Get_length(plist));
if(IsEmpty(plist))
{
return false;
}
//1.指针p指向待删除节点
//2.指针q指向待删除节点的上一个节点
//这里采用第二种方案找pq,先找q再找p
struct Clist *q = plist;
for(int i=0; i<pos; i++)
{
q = q->next;
}
struct Clist *p = q->next;
//3.跨越指向
q->next = p->next;
free(p);
return true;
}
//按值删除
bool Del_val(PClist plist, ELEMTYPE val)
{
//assert
struct Clist* p = Search(plist, val);
if(p == NULL)
{
return false;
}
struct Clist *q = plist;
for(q; q->next!=p; q=q->next);
q->next = p->next;
free(p);
return true;
}
//查找(如果查找到,需要返回找到的这个节点的地址)
struct Clist* Search(struct Clist *plist, ELEMTYPE val)
{
//assert
for(struct Clist *p=plist->next; p!=plist; p=p->next)
{
if(p->data == val)
{
return p;
}
}
return NULL;
}
//判空
bool IsEmpty(PClist plist)
{
//assert
return plist->next == plist;
}
//判满(循环链表不需要这个操作)
//获取长度
/*指针p从头结点的下一个节点开始向后跑,如果p再次遇到了头结点,
证明p走了一圈回来了,这是有效节点肯定已经遍历结束*/
int Get_length(PClist plist)
{
//不带前驱的for循环 跑一遍就好
int count = 0;
for(struct Clist *p=plist->next; p!=plist; p=p->next)
{
count++;
}
return count;
}
//清空
void Clear(PClist plist)
{
//assert
Destroy1(plist);
}
//销毁1(无限头删)
void Destroy1(PClist plist)
{
//assert
while(plist->next != plist)
{
struct Clist *p = plist->next;
plist->next = p->next;
free(p);
}
plist->next = plist;
}
//销毁2(要用到两个指针变量)
void Destroy2(PClist plist)
{
//assert
struct Clist *p = plist->next;
struct Clist *q = NULL;
plist->next = plist;
while (p!=plist)
{
q = p->next;
free(p);
p = q;
}
}
//打印
void Show(struct Clist *plist)
{
//assert
for(struct Clist *p=plist->next; p!=plist; p=p->next)
{
printf("%d ", p->data);
}
printf("\n");
}
最后在主函数中实现:
#include <stdio.h>
#include "assert.h"
#include <stdlib.h>
#include <vld.h>
#include "Clist.h"
int main()
{
struct Clist head;
Init_clist(&head);
for(int i=0; i<20; i++)
{
Insert_pos(&head, i, i+1);
}
Show(&head);
Insert_head(&head, 100);
Insert_tail(&head, 200);
Show(&head);
printf("length = %d\n", Get_length(&head));
Del_head(&head);
Del_tail(&head);
Show(&head);
printf("length = %d\n", Get_length(&head));
Del_pos(&head, 3);
Del_val(&head, 14);
Show(&head);
printf("length = %d\n", Get_length(&head));
//Destroy(&head);
Destroy2(&head);
return 0;
}