c语言实现循环链表(基于企业链表实现)

       循环链表,最后一个元素的next指向头结点,这是其核心。

       企业链表在结点结构体内只维护一个next指针,结点结构体是构成链表的本质,自定义的结构体内部需要包含一个结点结构体类型的变量。节点的连接和数据访问是通过显示的指针数据类型转换来实现的。

1.next指针连接着整个链表,可以形象理解为一条挂衣服的绳子。

2.每个数据结构体内部包含的结点结构体类型是用来挂衣服的挂钩。

3.头结点还有数据节点都是值形式,不需要手动开辟释放。

4.在每个数据结构体内,节点结构体变量都定义在最前面,这样在指针类型转换不用考虑偏移量就可以获取节点类型指针。

在编写时要注意的点为:

1.结点结构体内部定义next指针时,struct好像不能省略。

2.按值删除时,写法很灵活,在循环体内找到就可以删除,不需要在循环结束后进行额外判断(比较麻烦),删除节点后别忘了size--。

3.打印数据时,可以尝试多轮循环,在每一次遍历到头结点时,直接next。

4.循环链表不能通过结点判空来终止循环。

5字符数组的的比较用strcmp,不像string用==。

Circle_LinkList.h

#pragma once

//链表小节点
typedef struct CIRCLELINKNODE
{
	struct CIRCLELINKNODE* next;//struct不能省略,不然报错
}CircleLinkNode;

//链表结构体

typedef struct CIRCLELINKLIST
{
	CircleLinkNode head;
	int size;
}CircleLinkList;

//比较回调
typedef int (*COMPARENODE)(CircleLinkNode, CircleLinkNode);

//打印回调
typedef void (*PRINTNODE)(CircleLinkNode);

//针对链表结构体操作的API函数
#define CIRCLELINKLIST_TRUE 0
#define CIRCLELINKLIST_FALSE 1

//初始化函数
CircleLinkList* Init_CircleLinkList();

//插入函数
void Insert_CircleLinkList(CircleLinkList* clist, int pos, CircleLinkNode* data);

//获取第一个元素
CircleLinkNode* Front_CircleLinkList(CircleLinkList* clist);

//根据位置删除
void RemoveByPos_CircleLinkList(CircleLinkList* clist, int pos);

//根据值删除
void RemoveByValue_CircleLinkList(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare);

//获得链表长度
int Size_CircleLinkList(CircleLinkList* clist);

//判空
int IsEmpty_CircleLinkList(CircleLinkList* clist);

//查找
int Find_CircleLinkList(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare);

//打印结点
void Print_CircleLinkList(CircleLinkList* clist, PRINTNODE print);

//释放内存
void FreeSpace_CircleLinkList(CircleLinkNode* clist);

Circle_LinkList.c

#include"Circle_LinkList.h"
#include<stdio.h>
//针对链表结构体操作的API函数
//初始化函数
CircleLinkList* Init_CircleLinkList()
{
	CircleLinkList* clist = (CircleLinkList*)malloc(sizeof(CircleLinkList));
	clist->head.next = &(clist->head);
	clist->size = 0;
    
    return clist;
}

//插入函数
void Insert_CircleLinkList(CircleLinkList* clist, int pos, CircleLinkNode* data)
{
	if (clist == NULL || data ==NULL)
	{
		return;
	}

	if (pos < 0 || pos >= clist->size)
	{
		pos = clist->size;
	}
	//辅助指针变量找结点
	CircleLinkNode* pCurrent = &(clist->head);

	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}

	data->next = pCurrent->next;
	pCurrent->next = data;
	clist->size++;
}

//获取第一个元素
CircleLinkNode* Front_CircleLinkList(CircleLinkList* clist)
{
	if (clist == NULL)
	{
		return NULL;
	}
	return clist->head.next;
}

//根据位置删除
void RemoveByPos_CircleLinkList(CircleLinkList* clist, int pos)
{
	if (clist == NULL)
	{
		return;
	}

	if (pos<0 || pos>=clist->size)
	{
		return;
	}

	//根据pos找结点
	//辅助指针变量
	CircleLinkNode* pCurrent = &(clist->head);

	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	
	CircleLinkNode* pNext = pCurrent->next;//记录一下这个结点,不需要释放
	pCurrent->next = pCurrent->next->next;
    
	clist->size--;
}

//根据值删除
void RemoveByValue_CircleLinkList(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare)
{
	if (clist == NULL || data ==NULL)
	{
		return;
	}

	//这个是循环链表,不能通过不为空来循环
 
	//值判断,不需要从头节点开始
	//在循环内进行判断和删除,不要在循环外统一判断,复杂了
	//这里很灵活,要注意
	CircleLinkNode* pPrev = &(clist->head);
	CircleLinkNode* pCurrent = pPrev->next;
	for (int i = 0; i < clist->size; i++)
	{
		if (compare(pCurrent, data) == CIRCLELINKLIST_TRUE)//找到之后就可以在这里进行删除操作,在循环外面操作需要多判断一次
		{
			pPrev->next = pCurrent->next;
			clist->size--;
			break;
		}
		pPrev = pPrev->next;
		pCurrent = pPrev->next;
	}
}

//获得链表长度
int Size_CircleLinkList(CircleLinkList* clist)
{
	if (clist == NULL)
	{
		return -1;
	}
	return clist->size;
}

//判空
int IsEmpty_CircleLinkList(CircleLinkList* clist)
{
	if (clist == NULL)
	{
		return -1;
	}

	if (clist->size == 0)
	{
		return CIRCLELINKLIST_TRUE;
	}

	else
	{
		return CIRCLELINKLIST_FALSE;
	}
}

//查找
int Find_CircleLinkList(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare)
{

	if (clist == NULL || data == NULL)
	{
		return -1;
	}

	CircleLinkNode* pCurrent = clist->head.next;
	int flag = -1;
	for (int i = 0; i < clist->size; i++)
	{
		if (compare(pCurrent, data) == CIRCLELINKLIST_TRUE)
		{
			flag = i;
			break;
		}
		pCurrent = pCurrent->next;
	}
	return flag;
}

//打印结点
void Print_CircleLinkList(CircleLinkList* clist, PRINTNODE print)
{
	if (clist == NULL)
	{
		return;
	}

	//设置辅助指针变量
	CircleLinkNode* pCurrent = clist->head.next;//注意打印多遍的情况
	for (int i = 0; i < clist->size*3; i++)
	{
		if (pCurrent == &(clist->head))//头结点没有保存数据,每次到头结点后直接下一个
		{
			pCurrent = pCurrent->next;
			printf("----------------------------\n");
		}

		print(pCurrent);
		pCurrent = pCurrent->next;
	}
}

//释放内存
void FreeSpace_CircleLinkList(CircleLinkNode* clist)
{
	if (clist == NULL)
	{
		return;
	}

	free(clist);

}

循环链表.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "Circle_LinkList.h"
#include<vld.h>

typedef struct PERSON
{
	CircleLinkNode node;//关键点
	char name[64];
	int age;
	int score;
}Person;

void myPrint(CircleLinkNode* data)
{
	Person* p = (Person*)data;
	printf("Name: %s, age: %d,score %d\n", p->name, p->age, p->score);
}

int myCompare(CircleLinkNode* data1, CircleLinkNode* data2)
{
	Person* p1 = (Person*)data1;
	Person* p2 = (Person*)data2;

	if (strcmp(p1->name,p2->name)==0 && p1->age == p2->age && p1->score == p2->score)//注意字符数组的比较不像字符串,不能用==
	{
		return  CIRCLELINKLIST_TRUE;
	}

	else
	{
		return CIRCLELINKLIST_FALSE;
	}
}

int main()
{
	//创建循环链表
	CircleLinkList* clist = Init_CircleLinkList();

	//创建数据
	Person p1, p2, p3, p4, p5;//一次定义多个结构体变量

	strcpy(p1.name, "aaa");
	strcpy(p2.name, "bbb");
	strcpy(p3.name, "ccc");
	strcpy(p4.name, "ddd");
	strcpy(p5.name, "eee");

	p1.age = 10;
	p2.age = 20;
	p3.age = 30;
	p4.age = 40;
	p5.age = 50;

	p1.score = 91;
	p2.score = 92;
	p3.score = 93;
	p4.score = 95;
	p5.score = 97;

	//数据入链表
	Insert_CircleLinkList(clist, 100, (CircleLinkNode*)&p1);
	Insert_CircleLinkList(clist, 100, (CircleLinkNode*)&p2);
	Insert_CircleLinkList(clist, 100, (CircleLinkNode*)&p3);
	Insert_CircleLinkList(clist, 100, (CircleLinkNode*)&p4);
	Insert_CircleLinkList(clist, 100, (CircleLinkNode*)&p5);

	//打印数据
	Print_CircleLinkList(clist, myPrint);

	//根据值删除
	Person pDel;
	strcpy(pDel.name, "ccc");
	pDel.age = 30;
	pDel.score = 93;

	//根据值删除
	//RemoveByValue_CircleLinkList(clist, (CircleLinkNode*)&pDel, myCompare);

	//打印数据
	//Print_CircleLinkList(clist, myPrint);

    //获取第一个元素
	CircleLinkNode* ret = Front_CircleLinkList(clist);
	//myPrint(ret);

	//根据位置删除
	//RemoveByPos_CircleLinkList(clist, 3);
	//Print_CircleLinkList(clist, myPrint);

	//获得链表长度
	//int length = Size_CircleLinkList(clist);
	//printf("链表长度为: %d\n", length);

	判空
	//if (IsEmpty_CircleLinkList(clist) == CIRCLELINKLIST_TRUE)
	//{
	//	printf("链表为空\n");
	//}
	//else
	//{
	//	printf("链表不为空\n");
	//}

	/*Person pFind;
	strcpy(pFind.name, "ddd");
	pFind.age = 40;
	pFind.score = 95;*/

	//查找
	//int pos = Find_CircleLinkList(clist, (CircleLinkNode*)&pFind, myCompare);
	//printf("找的的位置:%d\n", pos);

	//释放空间
	FreeSpace_CircleLinkList(clist);

	system("pause");
	return 0;
}

测试结果:

插入:

按值删除:

 返回头结点:

按位置删除

 返回链表长度:

判空:

 查找:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值