当前位置:文档之家› 循环链表实例(猴子选大王)

循环链表实例(猴子选大王)


// 让q指向链表尾部结点
// 链表尾部指向空 // 循环体结束 // 链表尾 // 链表尾部指向链表头,
// 形成循环链表
// 函数体结束
12
// 被调用函数select,mm表示结点删除间隔 void select(int mm) { // 函数体开始 int x=0; // 声明整型值x,并初始化为0 struct mon *p,*q; // 声明结构指针p,q q=tail; // q赋值为tail,指向循环链表尾部 do // 直到型循环,用于循环删除指定间隔的结点 { // 循环体开始 p=q->next; // p赋值为q相邻的下一个结点 x=x+1; // x加1 if(x % mm==0) // x是否整除mm, { // 表示是否跳过指定间隔
// 输出被删掉的猴子号
}
} else q=p; }while(q!=q->next); head = q;
printf("被删掉的猴子号为%d号\n",p->num); q->next=p->next; // 删除此结点 free(p); // 释放空间
// q指向相邻的下一个结点p // 剩余结点数不为1,则继续循环 // head指向结点q,q为链表中剩余一个结点 13 // 函数体结束
3 4 8
q
8
这个do-while循环的退出条件是q==q->next。即当只 剩下一个结点时才退出循环。当然猴王非其莫属了。 这时,让头指针head指向q,head是全局变量,在 主程序最后输出猴王时要用head->num。 q
head
7
参考程序如下:
9
#include <stdio.h> #include <malloc.h> #define null 0
(3)最后一个结点要和头结点用下一语句链接到一起 tail = q; tail->next = head;
q
head
tail
6
5、删结点的函数select(int mm) mm为形式参数,从1至m报数,凡报到mm者删除其 所在的结点。 设计两个指针p和q。一开始让q指向链表的尾部q=tail。 让p指向q的下一个结点。开始时让p指向1#猴所在的结点。 用一个累加器x,初始时x=0,从1#猴所在结点开始让 x=x+1=1,如果mm是1的话,1#猴所在的p结点就要被删 除。有三条语句 printf(“被删掉的猴子号为%d号\n”,p->num); q->next = p->next; 演示 free(p);
head
p
1 2
q tail
8
7
这里free(p)是释放p结点所占用的内存空间的语句。 如果mm不是1而是3,程序会在do-while循环中, 让x加两次1,q和p一起移动两次,p指向3#所在结 点,q指向2#所在结点,之后仍然用上述三条语句 删去3#所在的结点。
演示
p q head
1 2
q p
p
11
for(i=2;i<=nn;i=i+1) // 利用循环结构构造链表
{ // 循环体开始 p=(struct mon *)malloc(LEN);// 为p分配内存空间 p->num=i; // 初始化p结点num域为i,表示猴子号 q->next=p; // 将p结点加到链表尾部
q=p;
p->next=null; } tail = q; tail->next=head; }
4
1、定义一个名为mon的结构 struct mon { int num; // 整数,表示猴子的编号 struct mon *next; // 指针,指向相邻的下一 只猴子 }
2、将链表的头指针head定义为全局变量。 struct mon*head; 3、主函数 用键盘输入猴子数n,输入数m,调用函数create建立一个 循环链表,模拟众猴围成一圈的情况。该函数的实参为n。 调用函数select,模拟1至m报数,让n-1只猴子逐一出列 的过程。即在具有n个结点的循环链表按报数m删除结点的 5 过程。该函数的实参为m,最后输出猴王的编号。
4、建立循环链表的函数create(int nn) 其中nn为形式参数。要从编号1到编号nn。思路是
(1)先做第1个结点,让其中的数据域p->num赋值为1,让 指针域赋值为null。之后让链头指针head指向第1个结点。 利用指针q记住这个结点,以便让指针p去生成下面的结 点。
(2)利用一个计数循环结构,做出第2个结点到第nn个结点。 并将相邻结点一个接一个链接到一起。
struct mon *head, *tail; // mon结构指针,全局变量
10
void create(int nn) { int i; struct mon *p,*q;
// 被调用函数 // 函数体开始 // 整型变量i,用于计数 // 声明mon结构指针p,q
// 为p分配内存空间 p=(struct mon *) malloc(LEN); p->num=1; p->next=null; head=p; q=p; // 初始化p结点num域为1 // 初始化p结点next域为空 // 链表头指针head赋值为p // q赋值为p
14
循环链表
1
循环链表
例:猴子选大王。 n只猴子围成一圈,顺时针方向从1到n编号。 之后从1号开始沿顺时针方向让猴子从1, 2,…,m依次报数,凡报到m的猴子,都让 其出圈,取消候选资格。然后不停地按顺时 针方向逐一让报出m者出圈,最后剩下一个 就是猴王。
2
演示:n=8, m=3
8
1
起始位置 2
7
3
void main() { int n,m; head = null;
Байду номын сангаас
// 主函数开始 // 函数体开始 // 声明整型变量n,m // 初始化head为空
printf("请输入猴子数\n"); // 提示信息 scanf("%d",&n); // 输入待插入结点数据 printf("请输入间隔m\n"); // 提示信息 scanf("%d",&m); // 输入间隔 create(n); // 调用函数create建立循环链表 select(m); // 调用函数select,找出剩下的猴子 printf("猴王是%d号\n",head->num); // 输出猴王 } // 函数体结束
// 预编译命令 // 内存空间分配 // 定义空指针常量
// 定义常量,表示结构长度 #define LEN sizeof(struct mon) struct mon { int num; struct mon *next; }; // 结构声明 // 整型数,用于记录猴子号 // mon结构指针
猴王
6 5
4
猴子被淘汰的顺序
3
6
1
5
2
8
4
3
说明:
如图1所示有8只猴子围成一圈,m=3。从1# 猴的位置开始,顺时针1至3报数,第一个出 圈的是3#;第二个出圈的是6#,第3个出圈 的是1#;第4个出圈的是5#;第5个是2#,第 6个是8#;第7个是4#。最后剩下一个是7#, 它就是猴王。
我们用循环链表来模拟这个选择过程。
相关主题