一、循环链表的介绍
循环链表是一种特殊类型的链表,其中链表中的最后一个节点指向链表中的第一个节点,形成循环的结构。与普通链表相比,循环链表可以在链表中的任何位置进行遍历,并且可以方便地实现循环操作。在循环链表中,每个节点通常包含一个数据元素和一个指向下一个节点的指针。链表中的最后一个节点的指针指向第一个节点,形成闭环。
二、循环链表的创建以及初始化
进行链表初始化时,以用户键盘输入“0” 作为结束标志,通过链表初始化函数,可直接规定了链表长度。
typedef struct Node{
int data;
struct Node* next;
}Node;
//结构体定义
void Node_init(Node **head){
int item;
Node* target;
printf("输入节点的值,输入0完成初始化\n");
while(1){
scanf("%d",&item); //item为从键盘输入插入节点的值
if( item==0 )return;
if((*head)==NULL){ //当循环链表头节点为空的时候
*head = (Node *)malloc(sizeof(struct Node));
if(!(*head))exit(0);
(*head)->data = item;
(*head)->next = *head;
}
else{
//找到最后一个节点进行尾插
for(target = *head; target->next != *head; target = target->next);
Node* temp = (Node *)malloc(sizeof(struct Node));
if(!temp)exit(0);
temp->data = item;
temp->next = *head;
target->next = temp;
}
}
}
三、菜单栏样式设置
本程序做了一个菜单选择页面,提供给用户从键盘输入选择不同的操作。效果如图:
代码部分:
void Style_set(){
int j,height = 5,width = 60;
for(j = 0; j < width; j++)printf("*");
printf("\n*");
for(j = 0; j < (width - 20)/2 ; j++)printf(" ");
printf("请输入要进行的操作选项:");
for(j = 0; j < (width - 30)/2 ; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(1).初始化链表");
for(j = 0; j < (width - 12)/2; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(2).插入新节点");
for(j = 0; j < (width - 12)/2; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(3).删除指定结点");
for(j = 0; j < (width - 16)/2; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(4).查找指定结点");
for(j = 0; j < (width - 16)/2; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(5).遍历链表");
for(j = 0; j < (width - 8)/2; j++)printf(" ");
printf("*\n");
for(j = 0; j < width; j++)printf("*");
printf("\n");
}
四、链表插入节点
这里写的函数可以指定链表位置进行插入。
void insert_node( Node** head,int i){
int j = 1;
Node* target = *head;
int item;
printf("请输入插入结点的值\n");
scanf("%d",&item);
if(!item) exit(0);
if(i == 1){
struct Node* temp = (Node*)malloc(sizeof(struct Node));
temp->data = item;
for( ;target->next != *head; target = target->next);
temp->next = *head;
target->next = temp;
*head = temp;
}
else{
if(!item)exit(0);
target = *head;
for( ; j < (i-1); j++)
target = target->next;
Node* temp = (Node*)malloc(sizeof(struct Node));
temp->data = item;
Node* p = target->next;
target->next = temp;
temp->next = p;
}
}
五、删除一个节点
与指定位置插入节点类似,在删除节点时同样也能够指定位置,通过找到指定位置的前驱节点,从前驱节点断开并将其next指向删除节点的下一个节点,最后在释放掉删除节点的内存。
void delete_node(Node **head,int i){
Node* target;
int j = 1;
if( i==1 ){//删除第一个结点
for(target = *head ; target != *head; target = target->next);
Node* temp = *head;
*head = (*head)->next;
target->next = *head;
free(temp);
}
else{
target = *head;
for( ; j < (i-1); j++)
target = target->next;//寻找删除位置结点的前驱结点
Node* temp = target->next;
target->next = temp->next;
free(temp);
}
}
六、按值查找对链表搜索
这里只传递结构体,不对其修改,因此不需要用指针指向结构体,将查找的值从链表的头节点开始逐个比较,当比较到最后一个节点依然没有找到时就提示找不到该元素,若找到则返回该节点所在的位置。
int Search_Node(Node* head, int value){
Node* target;
int i = 1;
for(target = head; target->data != value && target->next != head; ++i)
target = target->next;
if(target->next = head) //不存在该元素
return 0;
else
return i;
}
七、循环链表的遍历
与单链表的遍历仅多了对尾节点的下一节点是否是头节点的判断。
void PrintOut_Link(Node *head){
Node* temp = head;
printf("***********链表中的元素为************\n");
do
{
printf("%4d ",temp->data);
} while ((temp = temp->next) != head);
printf("\n");
}
八、主函数以及全部代码
void main(){
char opp;
int pos;
Node* head = NULL;
Style_set();
while( opp != '0'){
scanf("%c",&opp);
switch(opp){
case '1' :
Node_init(&head);printf("\n");
PrintOut_Link(head);
Style_set();
break;
break;
case '2' :
printf("请输入插入结点的位置\n");
scanf("%d",&pos);
insert_node(&head,pos);
printf("在%d处插入值后: \n",pos);
PrintOut_Link(head);
printf("\n");
Style_set();
break;//单个break
case '3' :
printf("请输入要删除结点的位置\n");
scanf("%d",&pos);
delete_node(&head,pos);
printf("在%d处值删除后: \n",pos);
PrintOut_Link(head);
printf("\n");
Style_set();
break;
case '4' :
printf("请输入要查找结点的值\n");
scanf("%d",&pos);
pos = Search_Node(head,pos);
if(pos == 0)printf("查无此值\n");
else printf("所查找值的位置是: %d \n",pos);
PrintOut_Link(head);
printf("\n");
Style_set();
break;
case '5' :
PrintOut_Link(head);
printf("\n");
Style_set();
break;
case '0' :
exit(0);
}
}
}
全部代码:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
typedef struct Node{
int data;
struct Node* next;
}Node;
void insert_node(Node **head,int i);
void Style_set();
void Node_init(Node **head);
void delete_node(Node **head,int i);
int Search_Node(Node* head, int value);
void PrintOut_Link(Node *head);
void main(){
char opp;
int pos;
Node* head = NULL;
Style_set();
while( opp != '0'){
scanf("%c",&opp);
switch(opp){
case '1' :
Node_init(&head);printf("\n");
PrintOut_Link(head);
Style_set();
break;
break;
case '2' :
printf("请输入插入结点的位置\n");
scanf("%d",&pos);
insert_node(&head,pos);
printf("在%d处插入值后: \n",pos);
PrintOut_Link(head);
printf("\n");
Style_set();
break;//单个break
case '3' :
printf("请输入要删除结点的位置\n");
scanf("%d",&pos);
delete_node(&head,pos);
printf("在%d处值删除后: \n",pos);
PrintOut_Link(head);
printf("\n");
Style_set();
break;
case '4' :
printf("请输入要查找结点的值\n");
scanf("%d",&pos);
pos = Search_Node(head,pos);
if(pos == 0)printf("查无此值\n");
else printf("所查找值的位置是: %d \n",pos);
PrintOut_Link(head);
printf("\n");
Style_set();
break;
case '5' :
PrintOut_Link(head);
printf("\n");
Style_set();
break;
case '0' :
exit(0);
}
}
}
void Node_init(Node **head){
int item;
Node* target;
printf("输入节点的值,输入0完成初始化\n");
while(1){
scanf("%d",&item);
fflush(stdout);
if( item==0 )return;
if((*head)==NULL){
*head = (Node *)malloc(sizeof(struct Node));
if(!(*head))exit(0);
(*head)->data = item;
(*head)->next = *head;
}
else{
for(target = *head; target->next != *head; target = target->next);
Node* temp = (Node *)malloc(sizeof(struct Node));
if(!temp)exit(0);
temp->data = item;
temp->next = *head;
target->next = temp;
}
}
}
void Style_set(){
int j,height = 5,width = 60;
for(j = 0; j < width; j++)printf("*");
printf("\n*");
for(j = 0; j < (width - 20)/2 ; j++)printf(" ");
printf("请输入要进行的操作选项:");
for(j = 0; j < (width - 30)/2 ; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(1).初始化链表");
for(j = 0; j < (width - 12)/2; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(2).插入新节点");
for(j = 0; j < (width - 12)/2; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(3).删除指定结点");
for(j = 0; j < (width - 16)/2; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(4).查找指定结点");
for(j = 0; j < (width - 16)/2; j++)printf(" ");
printf("*\n");
printf("*");
for(j = 0; j < (width - 20)/2; j++)printf(" ");
printf("(5).遍历链表");
for(j = 0; j < (width - 8)/2; j++)printf(" ");
printf("*\n");
for(j = 0; j < width; j++)printf("*");
printf("\n");
}
void insert_node( Node** head,int i){
int j = 1;
Node* target = *head;
int item;
printf("请输入插入结点的值\n");
scanf("%d",&item);
if(!item) exit(0);
if(i == 1){
struct Node* temp = (Node*)malloc(sizeof(struct Node));
temp->data = item;
for( ;target->next != *head; target = target->next);
temp->next = *head;
target->next = temp;
*head = temp;
}
else{
if(!item)exit(0);
target = *head;
for( ; j < (i-1); j++)
target = target->next;
Node* temp = (Node*)malloc(sizeof(struct Node));
temp->data = item;
Node* p = target->next;
target->next = temp;
temp->next = p;
}
}
void delete_node(Node **head,int i){
Node* target;
int j = 1;
if( i==1 ){//删除第一个结点
for(target = *head ; target != *head; target = target->next);
Node* temp = *head;
*head = (*head)->next;
target->next = *head;
free(temp);
}
else{
target = *head;
for( ; j < (i-1); j++)
target = target->next;//寻找删除位置结点的前驱结点
Node* temp = target->next;
target->next = temp->next;
free(temp);
}
}
int Search_Node(Node* head, int value){
Node* target;
int i = 1;
for(target = head; target->data != value && target->next != head; ++i)
target = target->next;
if(target->next = head) //不存在该元素
return 0;
else
return i;
}
void PrintOut_Link(Node *head){
Node* temp = head;
printf("***********链表中的元素为************\n");
do
{
printf("%4d ",temp->data);
} while ((temp = temp->next) != head);
printf("\n");
}