单向循环链表:
在单向链表中,头指针是相当重要的,因为单向链表的操作都需要头指针,所以如果头指针丢失或者破坏,那么整个链表都会遗失,并且浪费链表内存空间。
单向循环链表的构成:
如果把单链表的最后一个节点的指针指向链表头部,而不是指向NULL,那么就构成了一个单向循环链表。
单向链表结构图示:(以下示意图均摘自
来源:
http://blog.csdn.net/fisherwan/ar
)
单向循环链表的初始化:
当单向循环链表中只有一个节点时,那么这个节点的next指针指向的就是这个节点本身。
单向循环链表的创建:
单向循环链表的创建和单向链表很相似,不同的地方是新插入节点的next指向的不再是NULL,而是指向第一个节点。
代码如下:
遍历到链表的最后一个节点ptemp;
ptemp->next = pnew;
pnew->next = head;
单向循环链表的插入:
单向循环链表的插入与单向链表有所不同,因为单向循环链表首尾相连,所以没有从尾部插入的问题。
(1)从链表头部插入
将新插入的节点变为链表头部,next指向原来的第一个节点,在遍历整个链表找到链表末尾(即它的next指向的是head的那个节点),将这个节点的next指向新插入的节点,最后再将链表头指针指向新节点。
代码如下:
pnew->next = head->next;
ptemp = head;
while(ptemp->next != head)
//注意此时的遍历条件是
ptemp->next != head
ptemp = ptemp->next;
//退出while循环后ptemp指向链表尾部
ptemp->next = pnew;
head = pnew;
(2)从链表中间插入
此时插入的过程和单向链表的一样,找到要插入位置前驱节点ptemp,将新插入节点的next指向ptemp的next,再将ptemp的next指向新插入的节点pnew。
代码如下:
pnew->next = ptemp->next;
ptemp->next = pnew;
以上的顺序不能变
单向循环链表的删除:
删除操作与插入操作类似,也分为两种情况:
(1)在链表头部删除
将链表头指针指向第二个节点,再将最后一个节点的指针指向新插入的节点,最后释放掉原来第一个节点的内存空间
代码如下:
ptemp = head;
first = head;
while(ptemp->next != head)
ptemp = ptemp->next;
//退出while循环后ptemp指向链表尾部
head= head->next;//头指针指向第二个节点
ptemp->next = headt;//指向第二个节点
free(first);//释放掉原来的第一个节点
(2)在链表中间删除
找到要删除的链表的前驱节点ptr,将ptr的next指向pdelete的next,再释放掉pdelete的内存空间。
代码如下:
ptr = head;
while(ptr->next != del)
ptr = ptr->next;//退出循环后此时ptr为pdelete的前驱
pdelete = ptr->next;
ptr-next = pdelete->next;
单向循环链表的C语言实现:(codeblocks完美运行)
#include <stdlib.h>
#include <stdio.h>
typedef struct circle_list
{
int date;
struct circle_list *next;
}list;
//节点创建函数
list *creat_node()
{
//创建头节点
list *newnode = (list *)malloc(sizeof(struct circle_list));
if(newnode == NULL)
{
printf("创建头结点失败!\n");
}
else
{
newnode->next=NULL;
return newnode;
}
}
//插入数据到链表中
int insert_list(list *head)
{
//创建节点
int val;
printf("请输入要插入的元素:");
scanf("%d",&val);
list *newnode = creat_node();
newnode->date = val;
//判断头节点是否为NULL
if(head != NULL)
{
//遍历头节点,中间变量P
list *p = head;
//遍历头节点到,最后一个数据
while(p->next != head )
{
//错误,这样会改变头节的位置,必须使用中间变量进行变量
// head = head->next;
p = p->next;
}
//把最后一个节点赋新的节点过去
p->next = newnode;
newnode->next = head;
return 1;
}
else
{
printf("head is NULL\n");
return 0;
}
}
//遍历链表中的数据
int display(list *head)
{
if(head != NULL)
{
//遍历头节点,中间变量P
list *p = head;
//遍历头节点到,最后一个数据
while(p->next != head )
{
//错误,这样会改变头节的位置,必须使用中间变量进行变量
// head = head->next;
printf("%d ",p->next->date);
p = p->next;
}
//把最后一个节点赋新的节点过去
return 1;
}
else
{
printf("头结点为空!\n");
return 0;
}
}
int delete_list(list *head)
{
if(head == NULL)
{
printf("链表为空!\n");
return 0;
}
list *temp = head;
list *ptr = head->next;
int del;
printf("请输入你要删除的元素:");
scanf("%d",&del);
while(ptr != head)
{
if(ptr->date == del)
{
if(ptr->next == head)//循环结束的条件换成ptr->next == head
{
temp->next = head;
free(ptr);
return 1;
}
temp->next = ptr->next;
free(ptr);
//printf("元素删除成功!\n");
return 1;
}
temp = temp->next;
ptr = ptr->next;
}
printf("没有找到要删除的元素%d\n",del);
return 0;
}
int update_list(list *head)
{
if(head == NULL)
{
printf("链表为空!\n");
return 0;
}
list *temp = head;
int olddate,newdate;
printf("请输入要修改的元素:");
scanf("%d",&olddate);
printf("修改为:");
scanf("%d",&newdate);
while(temp->next != head)
{
if(temp->next->date == olddate)
{
temp->next->date = newdate;
return 1;
}
temp = temp->next;
}
printf("没有找到要修改的元素!\n");
return 0;
}
int seek_list(list*head)
{
if(head == NULL)
{
printf("链表为空!\n");
return 0;
}
int val,i=0;
printf("请输入要查找的元素:");
scanf("%d",&val);
list *p = head;
while(p->next != head)
{
i++;
if(p->next->date == val)
{
printf("找到元素%d,位置在%d\n",val,i);
}
p = p->next;
}
printf("没有找到该元素!\n");
return 0;
}
void menu()
{
system("cls");//清屏
printf("\t\t|===============================================|\t\t\n");
printf("\t\t|==================单向循环操作=================|\t\t\n");
printf("\t\t|===================1.插入元素==================|\t\t\n");
printf("\t\t|===================2.打印链表==================|\t\t\n");
printf("\t\t|===================3.删除元素==================|\t\t\n");
printf("\t\t|===================4.修改链表==================|\t\t\n");
printf("\t\t|===================5.查找元素==================|\t\t\n");
printf("\t\t|==请输入对应的数字执行对应的功能!(输入0退出)==|\t\t\n");
printf("\t\t|====== 作者:RXX 时间:2017/07/06 ======|\t\t\n");
printf("\t\t|===============================================|\t\t\n");
}
int main()
{
//创建头节点
list *head = creat_node();
//让头字节自我循环
head->next = head;
int num;
menu();
scanf("%d",&num);
//插入节点
while(num)
{
switch(num)
{
case 1:
{
printf("插入元素操作:\n");
if(insert_list(head))
printf("插入节点成功!\n");
else
printf("插入节点失败!\n");
break;
}
case 2:
{
printf("打印链表操作:\n");
display(head);
break;
}
case 3:
{
if(delete_list(head))
printf("删除节点成功!\n");
break;
}
case 4:
{
if(update_list(head))
printf("修改元素成功!\n");
break;
}
case 5:
{
if(seek_list(head))
printf("查找元素成功!\n");
break;
}
}
getch();
menu();
scanf("%d",&num);
//清空缓存区
//while(getchar()!='\n');
}
printf("\t\t|================感谢使用!再见!===============|\t\t\n");
return 0;
}