循环列表同单向链表唯一的区别是链表的最后一个结点中的指针域不再为NULL,而是指向头结点,如下图所示:
所以在单向的程序判定的条件上需要做些改动
头文件
#ifndef __FY_CIRCULARLIST_H
#define __FY_CIRCULARLIST_H
typedef int data_t;
struct node{
data_t data;
struct node* next;
};
//创建一个结点
struct node * creatNode(data_t data);
//创建一个循环列表
struct node * creatCircularlist(void);
//遍历循环列表
int list_show(struct node *H);
//在指定位置插入一个元素
int list_insert(struct node *H,int pos,data_t data);
//删除指定位置的结点
int list_delete(struct node *H,int pos);
//获取指定位置的元素
struct node * list_get(struct node *H ,int pos);
//释放循环链表
struct node * list_free(struct node *H);
#endif
C文件
#include "circularlist.h"
#include "stdio.h"
#include "stdlib.h"
//创建一个结点
struct node* creatNode(data_t data){
struct node *newnode = (struct node *)malloc(sizeof(struct node));
if(newnode == NULL) {
printf("创建结点失败,内存申请不成功!\n");
return NULL;
}
newnode->data = data;
newnode->next = NULL;
return newnode;
}
//创建一个循环列表
struct node *creatCircularlist(){
struct node *headNode = (struct node *)malloc(sizeof(struct node));
if(headNode == NULL){
printf("创建头结点失败,内存申请不成功!\n");
return NULL;
}
headNode->data = 0;
headNode->next = headNode;//next指向自己
return headNode;
}
//判定循环列表(头结点)是否存在
int isHead(struct node *H){
if(H == NULL) return 0;
return 1;
}
//在指定位置插入元素
/*
定义头结点的地址为-1
*/
int list_insert(struct node *H,int pos,data_t data){
if(isHead(H) == 0){
printf("插入结点失败,列表不存在!\n");
return -1;
}
if(pos<0){
printf("插入节点失败,位置不合法!\n");
return -1;
}
//为元素新建一个结点
struct node *newnode = (struct node *)malloc(sizeof(struct node));
if(newnode == NULL){
return -1;
}
newnode->data = data;
//定义一个相邻的结点指针
struct node *p = H;
struct node *q = H->next;
int i=0;
while(i<pos && q != H){
//指针后移,计数增加,当找到q结点的next域为头结点为止
p = q;
q = q->next;
i++;
}
if(i!=pos){
printf("插入结点失败,指定位置不存在!\n");
return -1;
}
newnode->next = q;
p->next = newnode;
printf("插入结点成功!\n");
return 0;
}
//删除指定位置结点
/*
定义头结点位置为-1
*/
int list_delete(struct node *H,int pos){
if(isHead(H) == 0){
printf("删除指定位置结点失败,链表不存在!\n");
return -1;
}
//头结点的位置为-1,头结点不能删除
if(pos<0){
printf("删除指定位置结点失败,位置不合法!\n");
return -1;
}
int i=0;
//定义两个相邻指针
struct node *p,*q;
p = H;
q = H->next;
//直到找到位置为止
while(i<pos && q != H){
p = q;
q = q->next;
i++;
}
if(i!=pos){
printf("删除指定位置结点失败,位置结点不存在!\n");
return -1;
}
//要删除的元素为q
p->next = q->next;
free(q);
printf("删除指定位置结点成功!\n");
return 0;
}
//遍历循环列表
int list_show(struct node *H){
if(isHead(H) == 0){
printf("遍历循环列表失败,链表不存在!\n");
return -1;
}
// if(H->next == H){
// printf("遍历循环列表失败,链表为空!\n");
// return -1;
// }
struct node *p = H->next;//指向第0个结点
while(p != H){
printf("%d ",p->data);
p = p->next;
}printf("\n");
return 0;
}
//获取指定位置的元素
struct node * list_get(struct node *H ,int pos){
if(isHead(H) == 0){
printf("获取指定位置元素失败,链表不存在!\n");
return NULL;
}
if(pos<0){
printf("获取指定位置元素失败,位置不合法!\n");
return NULL;
}
int i=0;
struct node *p = H->next;//指向第0个结点
while(i<pos && p->next != H){
p = p->next;//结点位置移动
i++;
}
if(i!=pos){
printf("获取指定位置元素失败,位置结点不存在!\n");
return NULL;
}
printf("获取指定位置元素成功,数据为:");
return p;
}
//释放循环列表
struct node * list_free(struct node *H){
if(isHead(H) == 0){
printf("释放循环列表失败,链表不存在!\n");
return NULL;
}
struct node *head = H;//记录头结点的地址
struct node *p = H;//定义一个临时指针指向头结点
while(p->next != head){
H = H->next;//头结点后移
free(p);//释放旧的头结点
p = H;
}
free(p);
printf("释放循环列表成功!\n");
return NULL;
}
测试代码:
#include "stdio.h"
#include "stdlib.h"
#include "circularlist.h"
int main(){
int value,pos;
//创建一个循环列表(头结点)
struct node *H = creatCircularlist();
printf("**************指定位置插入元素测试***************\n");
while(1){
printf("请输入对应位置及数据,如 2 3表示再第2个位置插入数据3\n");
printf("当输入-1 -1表示退出测试\n");
scanf("%d %d",&pos,&value);
if(pos == -1 && value == -1){
break;
}
int res;
res = list_insert(H,pos,value);
if(res == 0){
printf("新链表为:");
list_show(H);
}
}
printf("**************删除指定位置结点测试*****************\n");
while(1){
printf("请输入要删除的结点位置,输入-1代表结束测试!\n");
scanf("%d",&pos);
if(pos == -1){
break;
}
int res;
res = list_delete(H,pos);
if(res == 0){
printf("新链表为:");
list_show(H);
}
}
H = list_free(H);
H = creatCircularlist();
for(int i = 0;i<10;i++){
list_insert(H,i,i);
}
list_show(H);
printf("**************获取指定位置结点元素测试*****************\n");
while(1){
printf("请输入一个位置:输入-1代表结束测试!\n");
scanf("%d",&pos);
if(pos == -1) break;
struct node * res;
res = list_get(H,pos);
if(res != NULL){
printf("%d \n",res->data);
}
}
printf("**************释放循环列表测试*****************\n");
H = list_free(H);
return 0;
}
测试结果
指定位置插入
删除指定位置结点
指定位置插入
获取指定元素
By Urien 2021年2月4日 00:22:47