目录
魔术师发牌问题
问题描述:魔术师利用一副普通的扑克牌中的13张黑桃,预先将他们排好后叠放在一起,牌面朝下,对观众说:“我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?现场演示。”
一开始,魔术师数1,然后把最上面的那张牌翻过来,是黑桃A;然后将其放到桌面上;第二次,魔术师数1、2;将第一张牌放到手中未翻过的扑克牌的最下面,将第二张牌翻转过来,正好是黑桃2;第三次,魔术师数1、2、3;将第1、2张牌依次放到手中未翻过的扑克牌的最下面,将第三张牌翻过来正好是黑桃3;……直到将所有的牌都翻出来为止。问原来牌的顺序是如何的。
实现结果:
完成方法如下:
宏定义及结构体类型声明
typedef int ElemType ;
#define MAX_CARDS 13
typedef struct magician
{
ElemType data;
struct magician *next;
}magician , * Ptrmagician;
初始化
/*******************************************
* 函数名称:MagicianInit()
* 功能描述:魔术师发牌问题链表初始化
* 传入参数:无
* 返回值: 循环链表头指针
********************************************/
Ptrmagician MagicianInit()
{
Ptrmagician list = NULL;
Ptrmagician p,q;
int i;
q = list;
for(i =0; i< MAX_CARDS;i++)
{
p = (Ptrmagician)malloc(sizeof(magician));
p -> data = 0;/*初始状态不保存数据*/
if(list == NULL)
{
list = p;/*头结点*/
}
else
{
q -> next = p;
}
q = p;
}
q -> next = list;/*首尾相连*/
}
计算牌的顺序
/*******************************************
* 函数名称:Magician(Ptrmagician list)
* 功能描述:魔术师发牌问题中牌的顺序计算
* 传入参数:Ptrmagician list 传入的链表
* 返回值: 无
********************************************/
void Magician(Ptrmagician list)
{
Ptrmagician s;
int i;
int count = 2;/*第一张牌存有数据1,第二张牌在1之后的第二张*/
s = list;
s -> data = 1;
while(1)
{
for (i = 0; i < count; i++)
{
s = s -> next;
if(s -> data != 0)
{
s -> next;/*这里是指向,而不是赋值*/
i--;/*当前位置存有数据*/
}
}
if(s -> data == 0)
{
s -> data = count;
count++;
if(count == MAX_CARDS+1)
{
break;/*牌的顺序计算完成*/
}
}
}
}
最终实现
/*****************************************************************
* 函数名称:main()
* 功能描述:主函数
* 传入参数:无
* 返回值:0
* 魔术师发牌问题描述:
* 魔术师利用一副普通的扑克牌中的13张黑桃,预先将
* 他们排好后叠放在一起,牌面朝下,对观众说:“我不
* 看牌,只数数就可以猜到每张牌是什么,我大声数数,
* 你们听,不信?现场演示。”
* 一开始,魔术师数1,然后把最上面的那张牌翻过来,
* 是黑桃A;然后将其放到桌面上;第二次,魔术师数1、
* 2;将第一张牌放到手中未翻过的扑克牌的最下面,将
* 第二张牌翻转过来,正好是黑桃2;第三次,魔术师数
* 1、2、3;将第1、2张牌依次放到手中未翻过的扑克牌
* 的最下面,将第三张牌翻过来正好是黑桃3;……直到将
* 所有的牌都翻出来为止。问原来牌的顺序是如何的。
******************************************************************/
int main()
{
Ptrmagician m;
int i;
m = MagicianInit();
Magician(m);
printf("魔术师发牌问题中牌的顺序如下:\n");
for(i = 0; i< MAX_CARDS; i++)
{
printf("黑桃%d ", m ->data);
m = m -> next;
}
printf("\n");
DestoryList(m);
return 0;
}
拉丁方阵问题
拉丁方阵(Latin square):是一种 n × n 的方阵,在这种 n x n 的方阵里,恰有 n 种不同的元素,每一种不同的元素在同一行或同一列里只出现一次。
n等于5时方阵如下图:
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
2 | 3 | 4 | 5 | 1 |
3 | 4 | 5 | 1 | 2 |
4 | 5 | 1 | 2 | 3 |
5 | 1 | 2 | 3 | 4 |
实现结果:
实现方法:
宏定义及结构体类型声明
/*待处理数据类型*/
typedef int ElemType ;
/*结点结构*/
typedef struct latin
{
ElemType data;
struct latin *next;
}latin , * Ptrlatin;
循环链表初始化
/**********************************************
* 函数名称:LatinInit(int n)
* 功能描述:初始化一个循环链表
* 传入参数:int n 循环链表的长度
* 返回值:循环链表的头结点
***********************************************/
Ptrlatin LatinInit(int n)
{
Ptrlatin list = NULL;/*头结点*/
Ptrlatin p,q;
int i;
p = list;
for(i = 1; i <= n; i++)
{
q = (Ptrlatin)malloc(sizeof(latin));
q ->data = i;
if (list == NULL )
{
list = q;
}
else
{
p -> next = q;
}
p = q;
}
p ->next = list;
return list;
}
方阵生成
/**********************************************
* 函数名称:Latin(Ptrlatin list, int n)
* 功能描述:拉丁方阵问题主要计算过程
* 传入参数:Ptrlatin list 传入的循环链表
* int n 循环链表的长度
* 返回值:无
***********************************************/
void Latin(Ptrlatin list, int n)
{
Ptrlatin s = list;
int i,j;
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
printf("%d ",s ->data);
s = s -> next;
}
printf("\n");
s = s ->next;
}
}
最终实现
/**********************************************
* 函数名称:main()
* 功能描述:主函数
* 传入参数:无
* 返回值:0
* 问题:用循环链表实现拉丁方阵:
* ---------------------
* | 1 | 2 | 3 | 4 | 5 |
* ---------------------
* | 2 | 3 | 4 | 5 | 1 |
* ---------------------
* | 3 | 4 | 5 | 1 | 2 |
* ---------------------
* | 4 | 5 | 1 | 2 | 3 |
* ---------------------
* | 5 | 1 | 2 | 3 | 4 |
* ---------------------
* 方法:首先建立一个单向循环链表,之后进行双层
* 循环,内层循环打印,内层循环结束后,外
* 层循环对链表头指针后移一位
***********************************************/
int main()
{
Ptrlatin list;
int n;
printf("请输入拉丁方阵的大小:");
scanf("%d",&n);
list = LatinInit(n);
Latin(list,n);
return 0;
}
😜
🙃
O(∩_∩)O