循环链表
循环链表:和单链表相比,尾结点的next域不再指向null,而是指向头
头文件设计:
//结构体设计(头结点借用)
typedef int ELEM_TYPE;
typedef struct Node
{
ELEM_TYPE data;//数据域
struct Node *next;//指针域
}Node,*PNode;
//循环链表拥有的可执行函数声明
//初始化 (对于头结点进行赋初值)
void Init_Clist(struct Clist* plist);
//头插
bool Insert_head(struct Clist* plist,ELEM_TYPE val);
//尾插
bool Insert_tail(struct Clist* plist, ELEM_TYPE val);
//按位置插入
bool Insert_pos(struct Clist* plist, ELEM_TYPE val);
//头删
bool Del_head(PClist plist,int pos);
//按位置删除
bool Del_pos(PClist plist);
//按值删除
bool Del_val(PClist plist, ELEM_TYPE val);
//查找(如果找到要返回节点地址)
struct Clist* Seacher(struct Clist* plist, ELEM_TYPE 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(PClist plist);
源文件:
//初始化 (对于头结点进行赋初值)
void InitClist(struct Clist* plist)
{
//单链表初始化处理:1.数据域不处理,next域赋为空
//循环链表初始化处理:1.数据域不处理,next域不再赋值为空,而是指向自己
//assert
plist->next = plist;//plist的next域里面赋plist的地址值
}
//头插
bool Insert_head(struct Clist* plist, ELEM_TYPE val)
{
//assert
struct Clist* pnewnode = (struct Clist*)malloc(1 * sizeof(struct Clist));
assert(pnewnode != NULL);
pnewnode->data = val;
//指针域的赋值可以不写
//1.购买新节点完毕
//2.找到插入位置(因为是头插,所以不用找)
//3.插入
pnewnode->next = plist ->next;
plist->next = pnewnode;
return true;
}
//尾插
bool Insert_tail(struct Clist* plist, ELEM_TYPE 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(struct Clist* plist,int pos, ELEM_TYPE val)
{
//assert
struct Clist* pnewnode = (struct Clist*)malloc(1 * sizeof(struct Clist));
assert(pnewnode != NULL);
if (NULL == pnewnode)
{
return false;
}
struct Clist* p = plist;
for (int i = 0; i < pos; i++)
{
p = p->next;//p指向带插入合适位置
}
pnewnode->next = p->next;
p->next = pnewnode;
return true;
}
//头删
bool Del_head(PClist plist, int pos)
{
assert(plist != NULL);
assert(pos >= 0 && pos <= Get_length(plist));
if (IsEmpty(plist))
{
return false;
}
//1.指针p指向待删除节点
struct Clist* p = plist->next;
//2.指针q指向待删除节点的前一个节点
//q就是plist
//3.跨越指向
plist->next = p->next;
return true;
}
//尾删
bool Del_tail(PClist plist)
{
assert(plist != NULL);
if (IsEmpty(plist))
{
return false;
}
//1.指针p指向待删除节点
struct Clist* p = plist;
for (p; p->next != plist; p = p->next);
//2.指针q指向倒数第二个节点
struct Clist* q = plist;
for (q; q->next != p; q = q->next);
//q就是plist
//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指向待删除节点
struct Clist* p = plist;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
//2.指针q指向待删除节点的前一个节点
struct Clist* q = plist;
for (int i = 0; i < pos - 1; i++)
{
q = q->next;
}
//q就是plist
//3.跨越指向
q->next = p->next;//还有第二种方法
/*
struct Clist *q=plist;
for(q;q->next->next!=plist;q=q->next);//此时for结束,q指向倒数第二个节点
struct Clist *p=q->next;
//此方法就是先找到q,则p就是q的next域的
//这里q->next域不可能为NULL,由于q->next=plist->next而plist->next不就是首元素的地址
*/
return true;
}
//按值删除
bool Del_val(PClist plist, ELEM_TYPE val)
{
//assert
//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, ELEM_TYPE 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;
}
//判满(循环链表不需要)
//获取长度
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(PClist plist)
{
//assert
for (struct Clist* p = plist->next; p != plist; p = p->next)
{
printf("%d ", p->data);
}
printf("\n");
}
循环链表和单链表区别就在于尾结点的next域不再是NULL而是头结点的地址,因此在与单链表的编码对比中要注意,单链表中经常写NULL的位置很可能现在变成了地址,其余的功能和单链表的功能区别不大。