这是小甲鱼数据结构视频中的两题,主要用的数据结构是循环链表。。
魔术师发牌问题:有13张同样花色的牌按照一定顺序摆放,然后按照公差为1的等差数列逐次取出,在求要取出的牌的过程中未取出的牌将顺次加入到末尾,求出能够达成这样效果的牌序.
拉丁方阵问题,用N个不同数字排除N * N的方阵使之行和列的数字都不一样.
下面是代码:
#include "stdafx.h"
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
typedef int Elemtype;
typedef struct Node {
Elemtype data;
struct Node *next;
}List,*NodeList;
//构建循环链表//
NodeList Create_List(int CardNum) {
NodeList PHead = (Node *)malloc(sizeof(Node));
NodeList S,P; //动态创建结点
S = (Node *)malloc(sizeof(Node));//创建第一个结点
S->data = 0;
S->next = NULL;
PHead->next = S;//头结点指向第一个结点
P = S;
for (int i = 1; i < CardNum; i++) {
//创建剩下的CardNum-1个结点
S = (Node *)malloc(sizeof(Node));
S->data = 0;
S->next = NULL;
P->next = S;
P = S;
}
//退出循环的时候P,S指向最后一个结点
P->next = PHead->next;
free(PHead);
return P->next; //返回第一个结点
}
//遍历循环链表//
void Traverse(NodeList P) {
int count = 1;
NodeList P1 = P;
printf("NO.%d->%d\t", count, P1->data);
count++;
while (P1->next != P) {
P1 = P1->next;
printf("NO.%d->%d\t", count, P1->data);
count++;
}
//当退出循环的时候,P1指向最后一个结点
printf("\n");
}
//魔术师发牌问题解法//
void Magical_Card(NodeList P,int CardNum) {
//算法是按照等差数列递增的方法进行计数
//当到达的结点值为0的时候则跳过,重新计数
//也就是说要在所有为0的结点处进行牌的放置
int count = 1;
P->data = count; //头结点赋值为1
count++;
while (1) {
for (int i = 0; i < count; i++) {
//往后逐渐计数
P = P->next;
if (P->data != 0)
//此时表示这个位置已经放置过牌了
//也就是在表演魔术的时候已经把牌拿出去了
i--; //表示要重新计数
}
//退出循环之后P指向要填入数字的结点
P->data = count;
count++;
if (count == CardNum+1)
break;//退出条件就是13个数字全部填入了
}
}
//拉丁方阵问题解法//
void Latin_Matrix(NodeList P,int CardNum) {
//拉丁方阵实际上要指定两个指针,进行循环嵌套
//输出过一遍之后就进行换行
int i, j;
printf("拉丁方阵为:\n");
NodeList P1; //用来记录每行开始循环的位置
P1 = P; //第一行就是从第一个结点开始打印
for (i = 0; i < CardNum; i++) {
printf("%d\t", P->data);
P = P->next;
}
printf("\n");
for (i = 1; i < CardNum;i++) {
P1 = P1->next;
P = P1; //接下来每一次循环P1都会向后一位,P从P1位置开始
for (j = 0; j < CardNum; j++) {
printf("%d\t", P->data);
P = P->next;
}
printf("\n");
}
}
int main()
{
NodeList P;
P = Create_List(5);
Magical_Card(P,5);
Traverse(P);
Latin_Matrix(P,5);
return 0;
}
输出结果: