一、循环链表概念
循环链表是一种链式存储结构,它的最后一个结点指向头结点,形成一个环。
循环链表的操作和单链表的操作基本一致,差别仅仅在于算法中的循环条件有所不同。在循环链表中可以定义一个"当前"指针,这个指针通常称为游标,可以通过这个游标来遍历链表中的所有元素。
二、循环链表的特点
循环链表的特点如下:
最后一个节点的指针指向第一个节点,形成闭环。
可以通过任意节点进行遍历,每个节点都有下一个节点的指针。
在遍历时可以无限循环下去,不会出现尾部节点的空指针错误。
可以从任意节点开始遍历,选择一个合适的起始节点可提高操作效率。
不增加额外存储花销
三、循环链表的基础运算
循环链表是一种链式存储结构,它的最后一个结点指向头结点,形成一个环。循环链表的基本运算包括插入、删除、修改、查询等,下面简单介绍这些基本运算的算法:
- 插入
在循环链表的任意位置插入一个新节点,需要修改插入位置的前驱节点的指针,使其指向新节点,然后将新节点的指针指向其下一个节点。
2.删除
在循环链表中删除一个节点,需要修改被删除节点的下一个节点的指针,使其指向被删除节点的上一个节点。
3.修改
在循环链表中修改一个节点的值,只需要修改该节点的值即可,不需要修改其他节点的指针。
4.查询
在循环链表中查询一个节点是否为某个值,需要遍历链表,直到找到该节点或者遍历到链表的末尾。
四、循环链表的实现过程
(一)、初始化链表
{
if(1)
{
/*申请内存*/
(*Head) = (SingleLinkList*)malloc(sizeof(SingleLinkList));
/*判断内存申请是否成功*/
if(*Head == NULL)
{
printf("申请内存错误, 初始化失败![]\n");
return ;
}
(*Head)->next = *Head;
return 0;
}
else
{
printf("该链表已经初始化!请删除后再执行此操作![]\n");
return ;
}
}
(二)、插入元素(头插法)
int insert_head(SingleLinkList Head, DataType x)
{
SingleLinkNode *newNode;
if(0)
{
printf("链表未初始化![]\n");
return ;
}
newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
if(!newNode)
{
printf("申请节点内存空间失败![]\n");
return ;
}
newNode->data = x;
newNode->next = (*Head)->next;
(*Head)->next = newNode;
return 0;
}
(三)、插入元素(尾插法)
int insert_tail(SingleLinkList Head, DataType x)
{
SingleLinkNode *newNode;
SingleLinkNode *p;if(0)
{
printf("链表未初始化![]\n");
return ;
}
newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
if(!newNode)
{
printf("申请节点内存空间失败![]\n");
return ;
}newNode->data = x;
newNode->next = *Head;
p = (*Head);while(p->next!=*Head)
{
p = p->next;
}
p->next = newNode;
return 0;
}
(四)、指定位置插入元素
int insert(SingleLinkList Head, int i, DataType x)
{
int j;
SingleLinkNode *p;
SingleLinkNode *newNode;
/*对i进行判断,0<i<=length+1*/
if(i<1 || i>length(*Head)+1)
{
printf("位置i不是链表有效位置![]\n");
return ;
}
p = (*Head);
j = 1;while(j<i)
{
j++;
p = p->next;
}newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
newNode->data = x;
newNode->next = p->next;
p->next = newNode;
return 0;
}
(五)、删除元素
int delete(SingleLinkList Head, DataType x)
{
int i;
int j;
SingleLinkNode *p;
SingleLinkNode *q; /*要删除的元素x*/
i = find(*Head,x);
if(!i)
{
printf("元素x【%d】不存在!\n", x);
return ;
}
p = (*Head);
j=1;
while(j<i)
{
j++;
p = p->next;
}
q = p->next;
p->next = q->next;
free(q); /*释放内存*/
return 0;
}
(六)、查找元素
int find(SingleLinkList *Head, DataType x)
{
int i;
SingleLinkNode *p;
i = 1;
p = Head->next;
while( p!= Head && p->data != x) /*while( p!= Head && p->data != x) */
{
i++;
p = p->next;
}
if(p->next == Head)
{
return 0;
}
else
{
return i;
}
}
(七)、输出链表长度
int length(SingleLinkList *Head)
{
int len=0;
SingleLinkNode *p;
p = Head->next;
while(p!=Head)
{
len++;
p = p->next;
}
return len;
}
(八)、输出链表
void print(SingleLinkList *Head)
{
SingleLinkNode *p;
int i=0;p = Head->next;
if(p==Head)
{
printf("链表为空!\n");
return;
}
while(p!=Head)
{
printf("Node[%d]. = %d\n", ++i, p->data);
p = p->next;
}
}
五、完整DEMO
#include "SingleLinkList.h"
#include <stdlib.h>
#include <stdio.h>/*1. 初始化*/
int init(SingleLinkList Head)
{
if(1)
{
/*申请内存*/
(*Head) = (SingleLinkList*)malloc(sizeof(SingleLinkList));
/*判断内存申请是否成功*/
if(*Head == NULL)
{
printf("申请内存错误, 初始化失败![]\n");
return ;
}
(*Head)->next = *Head;return 0;
}
else
{
printf("该链表已经初始化!请删除后再执行此操作![]\n");
return ;
}
}
/*2. 插入元素,头插法*/
int insert_head(SingleLinkList Head, DataType x)
{
SingleLinkNode *newNode;
if(0)
{
printf("链表未初始化![]\n");
return ;
}
newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
if(!newNode)
{
printf("申请节点内存空间失败![]\n");
return ;
}
newNode->data = x;
newNode->next = (*Head)->next;
(*Head)->next = newNode;
return 0;
}
/*2. 插入元素, 尾插法*/
int insert_tail(SingleLinkList Head, DataType x)
{
SingleLinkNode *newNode;
SingleLinkNode *p;if(0)
{
printf("链表未初始化![]\n");
return ;
}
newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
if(!newNode)
{
printf("申请节点内存空间失败![]\n");
return ;
}newNode->data = x;
newNode->next = *Head;
p = (*Head);while(p->next!=*Head)
{
p = p->next;
}
p->next = newNode;
return 0;
}/*2. 插入元素,在位置i处插入元素x */
int insert(SingleLinkList Head, int i, DataType x)
{
int j;
SingleLinkNode *p;
SingleLinkNode *newNode;
/*对i进行判断,0<i<=length+1*/
if(i<1 || i>length(*Head)+1)
{
printf("位置i不是链表有效位置![]\n");
return ;
}
p = (*Head);
j = 1;while(j<i)
{
j++;
p = p->next;
}newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
newNode->data = x;
newNode->next = p->next;
p->next = newNode;
return 0;
}/*3. 删除元素, 删除值为x的元素*/
int delete(SingleLinkList Head, DataType x)
{
int i;
int j;i = find(*Head,x);
if(!i)
{
printf("元素x【%d】不存在!\n", x);
return ;
}
p = (*Head);
j=1;while(j<i)
{
j++;
p = p->next;
}
q = p->next;
p->next = q->next;free(q); /*释放内存*/
/*5. 查找值为x的元素,返回位置i */
int find(SingleLinkList *Head, DataType x)
{
int i;
SingleLinkNode *p;while( p!= Head && p->data != x)
{
i++;
p = p->next;
}if(p->next == Head)
{
return 0;
}
else
{
return i;
}}
/*4. 链表长度*/
int length(SingleLinkList *Head)
{
int len=0;
SingleLinkNode *p;p = Head->next;
while(p!=Head)
{
len++;
p = p->next;
}
return len;
}/*6.输出链表*/
void print(SingleLinkList *Head)
{
SingleLinkNode *p;
int i=0;p = Head->next;
if(p==Head)
{
printf("链表为空!\n");
return;
}
while(p!=Head)
{
printf("Node[%d]. = %d\n", ++i, p->data);
p = p->next;
}
}
#include <stdio.h>
#include <string.h>
#include "SingleLinkList.h"
#include "welcome.h"int main(int argc, char* argv[])
{
SingleLinkList *Head;
DataType x;
int i,m,n,cmd;for(i=0;i<strlen(welcome);i++)
{
printf("%c",welcome[i]);
for(m=0;m<1000;m++)
for(n=0;n<1000;n++)
{
;
}
}printf("-----------简单链表演示程序----------\n");
do
{
printf("1. 初始化链表表\n");
printf("2. 插入元素(头插法)\n");
printf("3. 插入元素(尾插法)\n");
printf("4. 插入元素(在位置i插入)\n");
printf("5. 查找元素x\n");
printf("6. 求链表长度\n");
printf("7. 输出链表\n");
printf("8. 删除元素\n");
printf("10. 帮助\n");
printf("0. 退出\n");
printf("请输入您要进行的操作(1~10,0退出):");
scanf("%d", &cmd);
switch(cmd)
{
case 1:
if(!init(&Head))
{
printf("链表已初始化!\n");
}
break;
case 2:
printf("请输入插入元素x:x=");
scanf("%d",&x);
if(!insert_head(&Head,x))
{
printf("元素(%d)已插入\n", x);
}
break;
case 3:
printf("请输入插入元素x:x=");
scanf("%d",&x);
if(!insert_tail(&Head,x))
{
printf("元素(%d)已插入\n", x);
}
break;
case 4:
printf("请输入插入元素位置i和元素x(i,x):");
scanf("%d,%d", &i, &x);
if(!insert(&Head, i, x))
{
printf("已在位置(%d)插入元素(%d)!\n",i, x);
}
break;
case 5:
printf("请输入要查找的元素x:");
scanf("%d", &x);
if(i = find(Head,x))
{
printf("元素%d存在,在链表位置%d.\n", x, i);
}
else
{
printf("在链表中未找到元素x。\n");
}
break;
case 6:
printf("链表的长度为:%d\n", length(Head));
break;
case 7:
print(Head);
break;
case 8:
printf("请输入要删除的元素x:");
scanf("%d", &x);
if(!delete(&Head, x))
{
printf("元素x【%d】已删除!\n", x);
}
break;
case 10:
printf(" 本程序为链表的演示程序,由陈嘉俊设计开发,程序完成了插入,查找,删除等功能\n");
break;
}
}while(cmd != 0);
六、运行结果展示
七、总结
本文简单介绍了循环链表的基本概念,特点以及基础运算,并附上了代码以及结果,希望以后复习时可以加深自己的印象;在运行过程中,总有一些卡壳的部分,在朋友的指导下,修改代码并顺利完成结果。
八、参考文献
1:CSDN博客
2:季老师的代码
3:AL
4:朋友的指导