[循环链表]——单向循环链表

单向循环链表与普通链表的区别在于:普通链表的最后一个链表的next指向NULL,而单向循环链表的最后一个节点的next指向头结点

 头文件:

#ifndef CIRCLELINKLIST
#define CIRCLELINKLIST
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//链表小节点
typedef struct CIRCLELINKNODE {
	struct CIRCLELINKNODE* next;
}CircleLinkNode;

//链表结构体
typedef struct CIRCLELINKLIST {
	CircleLinkNode head;
	int size;
}CircleLinkList;

//定义真假宏
#define CIRCLELINKLIST_TRUE 1
#define CIRCLELINKLIST_FALSE 0

//比较回调函数
typedef int(*COMPARENODE)(CircleLinkNode*, CircleLinkNode*);
//打印回调函数
typedef void(*PRINTNODE)(CircleLinkNode*);

//针对链表结构体操作的API函数
//链表初始化函数
CircleLinkList* initCircleLinkList();
//插入函数
void insertByPos(CircleLinkList* clist, int pos, CircleLinkNode* data);
//获得第一个元素
CircleLinkNode* getFront(CircleLinkList* clist);
//根据位置删除
void removeByPos(CircleLinkList* clist, int pos);
//根据值删除
void removeByValue(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare);
//获取链表长度
int getSize(CircleLinkList* clist);
//判断是否为空
int isEmpty(CircleLinkList* clist);
//根据值查找
int findByValue(CircleLinkList* clist, CircleLinkNode* data, COMPARENODE compare);
//打印节点
void printList(CircleLinkList* clist, PRINTNODE print);
//释放内存
void freeSpace(CircleLinkList* clist);

#endif

API实现:

#include "CircleLinkList.h"

//针对链表结构体操作的API函数
//链表初始化函数
CircleLinkList* initCircleLinkList() {
	CircleLinkList* clist = (CircleLinkList*)malloc(sizeof(CircleLinkList));

	//链表数据初始化
	clist->head.next = &(clist->head);
	clist->size = 0;
	return clist;
}

//插入函数
void insertByPos(CircleLinkList* clist, int pos, CircleLinkNode* data) {
	if (clist == NULL) {
		return;
	}
	if (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* getFront(CircleLinkList* clist) {
	return clist->head.next;
}

//根据位置删除
void removeByPos(CircleLinkList* clist, int pos) {
	if (clist == NULL) {
		return;
	}
	if (pos < 0 || pos > clist->size) {
		return;
	}

	CircleLinkNode* pCurrent = clist->head.next;
	for (int i = 0; i < pos; i++) {
		pCurrent = pCurrent->next;
	}
	//缓存当前节点的下一个节点
	CircleLinkNode* pNext = pCurrent->next;
	pCurrent->next = pNext->next;
	clist->size--;
}

//根据值删除
void removeByValue(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 = pCurrent;
		pCurrent = pCurrent->next;
	}
}

//获取链表长度
int getSize(CircleLinkList* clist) {
	return clist->size;
}

//判断链表是否为空
int isEmpty(CircleLinkList* clist) {
	if (clist->size == 0) {
		return CIRCLELINKLIST_TRUE;
	}

	return CIRCLELINKLIST_FALSE; //返回0表示,非空
}

//根据值查找
int findByValue(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 printList(CircleLinkList* clist, PRINTNODE print) {
	if (clist == NULL) {
		return;
	}

	CircleLinkNode* pCurrent = clist->head.next;
	for (int i = 0; i < clist->size; i++) {
		print(pCurrent);
		pCurrent = pCurrent->next;
	}
}

//释放内存
void freeSpace(CircleLinkList* clist) {
	if (clist == NULL) {
		return;
	}
	free(clist);
}

测试代码:

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

//测试结构体
typedef struct PERSON {
	CircleLinkNode node; //连接各个数据
	char name[64];
	int age;
}Person;

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

//1代表相同,0代表不同
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) {
		return CIRCLELINKLIST_TRUE;
	}

	return CIRCLELINKLIST_FALSE;
}

void test01() {
	CircleLinkList* clist = initCircleLinkList();

	//创建测试数据
	Person p1, p2, p3, p4, p5, p6;
	strcpy(p1.name, "aaa");
	strcpy(p2.name, "bbb");
	strcpy(p3.name, "ccc");
	strcpy(p4.name, "ddd");
	strcpy(p5.name, "eee");
	strcpy(p6.name, "fff");
	p1.age = 30;
	p2.age = 40;
	p3.age = 50;
	p4.age = 60;
	p5.age = 70;
	p6.age = 80;

	//插入数据到链表结构
	insertByPos(clist, 0, (CircleLinkNode*)(&p1));
	insertByPos(clist, 0, (CircleLinkNode*)(&p2));
	insertByPos(clist, 0, (CircleLinkNode*)(&p3));
	insertByPos(clist, 0, (CircleLinkNode*)(&p4));
	insertByPos(clist, 0, (CircleLinkNode*)(&p5));
	insertByPos(clist, 0, (CircleLinkNode*)(&p6));

	//打印数据
	printList(clist, myPrint);
	printf("===============================\n");

	//删除数据
	removeByPos(clist, 2);
	printList(clist, myPrint);
	printf("===============================\n");

	//查找数据
	Person findP;
	strcpy(findP.name, "ccc");
	findP.age = 50;
	int flag = findByValue(clist, &findP, myCompare);
	if (flag == CIRCLELINKLIST_TRUE) {
		printf("数据 %s 找到了\n", findP.name);
	} else {
		printf("数据 %s 未找到了\n", findP.name);
	}
}

int main(void) {
	test01();
	system("pause");
	return 0;
}

约瑟夫问题:

约瑟夫问题的源头完全可以命名为“自杀游戏”。本着和谐友爱和追求本质的目的,我们把问题描述如下:

  • 现有M个人围成一桌坐下,编号从1到M,从编号为1的人开始报数。
  • 报数也从1开始,报到N的人离席,从离席者的下一位在座成员开始,继续从1开始报数。
  • 复现这个过程(各成员的离席次序),或者求最后一个在座的成员编号。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CircleLinkList.h"

//环内数据总数,N走一步出列
#define M 8
#define N 3

//存储的数据
typedef struct MYNUM {
	CircleLinkNode node;
	int val; //存储的数据编号
}MyNum;

//打印回调实现
void myPrint1(CircleLinkNode* data) {
	MyNum* num = (MyNum*)data;
	printf("%d ", num->val);
}

//比较回调打印
int myCompare1(CircleLinkNode* data1, CircleLinkNode* data2) {
	MyNum* m1 = (MyNum*)data1;
	MyNum* m2 = (MyNum*)data2;
	
	if (m1->val == m2->val) {
		return CIRCLELINKLIST_TRUE;
	}
	return CIRCLELINKLIST_FALSE;
}

void josephus() {
	//创建循环链表
	CircleLinkList* clist = initCircleLinkList();
	//链表中插入数据
	MyNum myNum[8]; //数据数组
	for (int i = 0; i < 8; i++) {
		myNum[i].val = i + 1;
		insertByPos(clist, i, (CircleLinkNode*)&myNum[i]);
	}

	//打印环内数据
	printList(clist, myPrint1);
	printf("\n");

	int index = 1; //表示当前位置
	CircleLinkNode* pCurrent = clist->head.next;
	while (getSize(clist) > 1) {
		if (index == N) {
			MyNum* tempNum = (MyNum*)pCurrent;
			printf("%d ", tempNum->val);

			//缓存待删除节点的下一个节点
			CircleLinkNode* pNext = pCurrent->next;
			//根据值删除
			removeByValue(clist, pCurrent, myCompare1);

			//判断是否是头结点,是的话需要跳过去
			pCurrent = pNext;
			if (pCurrent == &(clist->head)) {
				pCurrent = pCurrent->next;
			}

			//重置index值
			index = 1;
		}

		pCurrent = pCurrent->next;
		if (pCurrent == &(clist->head)) {
			pCurrent = pCurrent->next;
		}
		index++;
	}
	printf("\n");

	if (getSize(clist) == 1) {
		MyNum* font = (MyNum*)getFront(clist);
		printf("最终筛选出的是 %d\n", font->val);
	}
	else {
		printf("筛选出错!!!!\n");
	}

	//释放链表内存
	freeSpace(clist);
}

int main(void) {
	josephus();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Star星屹程序设计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值