数据结构——循环链表

对于循环链表,我是通过一道例题来学习的:
约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 n 个人(以编号1,2,3,…,n分别表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,要求找到最后出列的那个人。
当然,我们可以用数学知识来求解,通过找规律什么的应该是可以解的,但是我觉得咱写代码的应该对自己好点,比较头发不好保养,还是让计算机来解决这个问题吧~
我们可以很明确的知道这里我们需要用到循环来解决问题。那么循环链表就可以在这里出场了:循环链表其实很好理解,就是将之前的链表头尾相连。其他的地方和循环链表几乎一模一样~
接下来就是将这个题目的代码整理出来给大家了:

#include<stdio.h>
#include<stdlib.h>

typedef struct node{
	int number;
	struct node *next;
}person;

/*初始化循环列表*/
person *initLink(int n){
	person *head = (person *)malloc(sizeof(person));
	head->number = 1;
	head->next = NULL;
	person *cyclic = head;
	/*head作为头指针,不能移动,不然咱也就找不到这个链表了,
	所以这个时候我们申请一个新的cyclic来往下遍历创建新的结点*/ 
	int i;
	for(i = 2; i <= n; i++){
		/*用body创立新的结点*/ 
		person *body = (person *)malloc(sizeof(person));  
		body->number = i; 
		body->next = NULL;
		cyclic->next = body;//将前后的结点连接起来 
		cyclic = cyclic->next;
	}
	cyclic->next = head;
	return head;
} 

void findAddKillK(person *head, int k, int m){
	person *tail = head;
	/*找到链表的结尾*/
	while(tail->next != head){
		tail = tail->next;
	}
	/*用p来找到我们的起点*/
	person *p = head;
	while( p->number != k){
		tail = p;
		p = p->next;
	} 
	
	/*找到我们需要删除的结点*/ 
	while(p->next != p){
		int i;
		for( i = 1; i < m; i++){
			tail = p;
			p = p->next;
		} //此时的p指向我们需要删除的结点 
		tail->next = p->next; //将p的前一个结点连向它的后一个结点 
		printf("出列表的人为%d", p->number);
		free(p); //释放空间 
		p = tail->next;
	}
	printf("出列表的人为%d", p->number);
	free(p); //最后将自己给释放 
}

int main(){
	int n,m,k;
	printf("圆桌上共有:" );
	scanf("%d", &n); 
	person * head = initLink(n);
	printf("从第k人开始报数:");
	scanf("%d", &k); 
	printf("数到m个人出列:");
	scanf("%d", &m); 
	findAddKillK(head, k, m);
} 

我是不会说我犯错居然把取地址符曾经漏了,找不到错差点崩溃的~

发布了14 篇原创文章 · 获赞 3 · 访问量 696

猜你喜欢

转载自blog.csdn.net/qq_44961028/article/details/99724583