【数据结构学习】单向循环链表的创建,指定位置插入、查找、删除及释放

循环列表同单向链表唯一的区别是链表的最后一个结点中的指针域不再为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

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
链表是一种常见的数据结构,它由一系列结点组成,每个结点包含两个部分:数据域和指针域。数据域用来存储数据,指针域用来指向下一个结点。链表有单向链表、双向链表、循环链表等多种形式。 下面是创建一个单向链表并进行初始化,对链表进行插入删除查找和更改的算法思路: 1. 定义链表结构体 ```c struct ListNode { int val; struct ListNode *next; }; ``` 2. 创建链表并初始化 ```c struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode)); head->val = 0; // 头结点不存储数据 head->next = NULL; ``` 3. 插入结点 ```c void insert(struct ListNode *head, int index, int val) { struct ListNode *cur = head; for (int i = 0; i < index && cur != NULL; i++) { cur = cur->next; } if (cur == NULL) { return; } struct ListNode *newNode = (struct ListNode*)malloc(sizeof(struct ListNode)); newNode->val = val; newNode->next = cur->next; cur->next = newNode; } ``` 4. 删除结点 ```c void delete(struct ListNode *head, int index) { struct ListNode *cur = head; for (int i = 0; i < index && cur != NULL; i++) { cur = cur->next; } if (cur == NULL || cur->next == NULL) { return; } struct ListNode *tmp = cur->next; cur->next = cur->next->next; free(tmp); } ``` 5. 查找结点 ```c int search(struct ListNode *head, int val) { struct ListNode *cur = head->next; int index = 0; while (cur != NULL && cur->val != val) { cur = cur->next; index++; } if (cur == NULL) { return -1; } else { return index; } } ``` 6. 更改结点 ```c void update(struct ListNode *head, int index, int val) { struct ListNode *cur = head->next; for (int i = 0; i < index && cur != NULL; i++) { cur = cur->next; } if (cur == NULL) { return; } cur->val = val; } ``` 以上是单向链表的基本操作,可以根据实际需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值