线性表---循环链表

循环链表:循环链表的特点是可以通过尾结点的指向找到头结点的地址;

结构体设计与单链表相同:

typedef int ELEM_TYPE;

typedef struct Clist
{
	ELEM_TYPE data;     //数据域      
	struct Clist* next; //指针域      

} Clist, * PClist;

主要功能实现如下:

1.初始化操作

循环列表初始化操作中需要将首节点的next域指向它本身的地址

void Init_clist(struct Clist* plist)
{
	assert(plist != NULL);
	if (plist == NULL)
	{
		return;
	}
	plist->next = plist;
}

2.尾插函数

首先申请一个新节点pnewnode,然后将其next域指向首节点的地址,然后再申请一个临时节点p将其指向尾结点的地址,然后让p的next域指向pnewnode的地址。

bool Insert_tail(PClist plist, ELEMTYPE val)
{
	assert(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	//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;
}

循环链表完整代码

clist.h

//循环链表结构体设计
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);

clist.cpp

#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include "clist.h"

//循环链表里边很少出现NULL, nullptr

//初始化
void InitClist(struct Clist* plist)
{
	assert(plist != NULL);
	if (plist == NULL)
	{
		return;
	}

	//plist->data; // 数据域不处理
	plist->next = plist;
}

//头插
bool Insert_head(PClist plist, ELEMTYPE val)
{
	assert(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	//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(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	//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);
	if (plist == NULL)
	{
		return false;
	}
	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(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	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(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	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);
	if (plist == NULL)
	{
	      return false;
	}
	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(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	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(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	for(struct Clist *p=plist->next; p!=plist; p=p->next)
	{
		if(p->data == val)
		{
			return p;
		}
	}

	return NULL;
}

//判空
bool IsEmpty(PClist plist)
{
	assert(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	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(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	Destroy1(plist);
}

//销毁1(无限头删)
void Destroy1(PClist plist)
{
	assert(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	while(plist->next != plist)
	{
		struct Clist *p = plist->next;
		plist->next = p->next;
		free(p);
	}

	plist->next = plist;
}

//销毁2(要用到两个指针变量)
void Destroy2(PClist plist)
{
	assert(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	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(plist != NULL);
	if (plist == NULL)
	{
		return false;
	}
	for(struct Clist *p=plist->next; p!=plist; p=p->next)
	{
		printf("%d ", p->data);
	}
	printf("\n");
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值