这是15年前,环球科学杂志上的一篇文章,作者写了一个类似简单魔方的小游戏:M12
这是游戏说明:
给大家翻译一下:
游戏由两个按键控制,一个是“INVERT“,另一个是“MERGE”。“INVERT”英文的意思是“反向“,能将“1,2,3,4,…,12“,排列成“12,11,10…,1”,而“MERGE”英文的意思是“混合”,能将“1,2,3,4,…,12“,排列成“1,12,2,11,3,10,4,9,5,8,6,7”,如图:
游戏开始时按下“RANDOMIZE”(随机)键,将数字打乱,让玩家通过这两个键还原,这是不是类似魔方的玩法,“CUSTOM”键可以将一组“IMIM…“的按键方式记下来,自定义这样的组合。
游戏并不是没有规律,当"INVERT"按两次就回归原始状态了,这里就不做演示了。””"MERGE"则是按下11次就回归原始状态,如下图:
这时再按一次“MERGE”,就恢复了最初的状态。
因此整个过程能用一个二叉树表示:
我们用的是广度优先算法,从顺序上看是这样的:
这里面不排除有重复值,这个可以在软件中筛选掉。
游戏提示中写道,这将有12×11×10×9×8种(95040种)组合,软件在遍历过程中实际用时8小时,因为我每做多线程,操作太麻烦,因此我我的思路是这样的,我从不打乱的状态去遍历,排除掉重复的,将遍历得到的结果和路径全部记下,这样我打乱之后直接在记录中查找,找到还原的最短路径,再按记下的路径还原,这样只需要跑一次8小时,永久不耗时,记录也只用了9kB的硬盘空间。
#include <stdio.h>
#include <malloc.h>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define MaxSize 2000000//如果没有运行完就退出,修改这里
#define GuangduZize 800//M12,1000000;M6,800
#define ShuzuSize 1000//M12,1000000;M6,1000
typedef char ElemType;
typedef struct node{
long data; //数据元素
int shuzu[12];
struct node *lchild, *rchild; //指向左孩子右孩子
}BTNode, *Bitree;
BTNode *que[30000];
FILE* fp;
int record[ShuzuSize][12];
int flag;//find " 1 2 3 4 5 6 7 8 9 10 11 12"
int sameflag;
long front = 0, rear = 0;
void DispPath4(BTNode *b,int ch);
/*******************
queue
*******************/
typedef struct _q_node
{
BTNode *t_node;
struct _q_node *next;
}QNode;
typedef struct _Queue
{
QNode *head;
QNode *tail;
}Queue;
Queue* init_queue()
{
Queue *queue=(Queue*)malloc(sizeof(Queue));
queue->head = queue->tail = NULL;
return queue;
}
int enQueue(Queue *pQueue,BTNode *pTNode)
{
QNode *pQNode = (QNode *)malloc(sizeof(QNode));
pQNode->t_node = pTNode;
if(pQueue->head == NULL)
{//when it's empty
pQueue->head = pQNode;
pQueue->tail = pQNode;
}
else
{
pQueue->tail->next = pQNode;
pQueue->tail = pQNode;
}
return 0;
}
QNode* deQueue(Queue *pQueue)
{
if(pQueue->head == NULL)
{
return NULL;
}
QNode *deNode= pQueue->head;
pQueue->head = pQueue->head->next;
return deNode;
}
BTNode* init_TNode(int data)
{
BTNode *new_node = (BTNode*)malloc(sizeof(BTNode));
new_node->data=data;
new_node->lchild = new_node->rchild = NULL;
return new_node;
}
//0:empty
int ifEmpty(Queue *pQueue)
{
if(pQueue->head == NULL)
{
//printf("empty tree\n");
return 0;
}
//printf("queue is not empty\n");
return 1;
}
/**************************
**************************/
int merge(int* input, int* output)
{
output[0]=input[0];
output[1]=input[11];
output[2]=input[1];
output[3]=input[10];
output[4]=input[2];
output[5]=input[9];
output[6]=input[3];
output[7]=input[8];
output[8]=input[4];
output[9]=input[7];
output[10]=input[5];
output[11]=input[6];
return 1;
}
int invert(int* input, int* output)
{
int temp,k=0;
merge(input, output);
while(k<6)//12/2
{
temp=input[k];
output[k]=input[11-k];//12-k-1
output[11-k]=temp;//12-k-1
k++;
}
return 1;
}
int merge6(int* input, int* output)
{
output[0]=input[0];
output[1]=input[5];
output[2]=input[1];
output[3]=input[4];
output[4]=input[2];
output[5]=input[3];
return 1;
}
int invert6(int* input, int* output)
{
int temp,k=0;
merge6(input, output);
while(k<3)//6/2
{
temp=input[k];
output[k]=input[5-k];//12-k-1
output[5-k]=temp;//12-k-1
k++;
}
return 1;
}
int findFlag(int n[]){
if(flag==0 | (n[0]==1 && n[1]==2 && n[2]==3 && n[3]==4 && n[4]==5)){
return 0;
}else{
return 1;
}
}
int findSameFlag4(int n[]){
long i;
for(i=0;i<ShuzuSize;i++){
//fprintf(fp,"%3d\t%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d\n",i,n[0],n[1],n[2],n[3],n[4],n[5],record[i][0],record[i][1],record[i][2],record[i][3],record[i][4],record[i][5]);
if(n[0]==record[i][0] && n[1]==record[i][1] && n[2]==record[i][2] && n[3]==record[i][3] && n[4]==record[i][4]){
return 0;
}
}
return 1;
}
BTNode* CreateBiTree(int n[12])//m6,层序创建二叉树
{
static BTNode *t, *bt, *q;
long x=1;
int i,j;
//1
bt = (BTNode*)malloc(sizeof(BTNode));
bt->data = 0;
for(i=0;i<6;i++){
bt->shuzu[i]=n[i];
}
for(j=0;j<6;j++){//将数组写入已打印队列,以便查找有无重复
record[0][j]=n[j];
}
bt->rchild = bt->lchild = NULL;
que[rear++] = bt;
while(x<GuangduZize & front<rear){
t = que[front];
front++;
//M,left
if(flag){
merge6(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x;
for(i=0;i<6;i++){
q->shuzu[i]=n[i];
}
flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<6;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->lchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->lchild = NULL;
printf("找到序号为:%d\n",x-1);
break;
}
if(flag){
invert6(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x+1;
for(i=0;i<6;i++){
q->shuzu[i]=n[i];
}
flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<6;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->rchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->rchild = NULL;
printf("找到序号为:%d\n",x);
break;
}
x+=2;
}
return bt;
}
BTNode* CreateBiTree2(int n[12])//m6,由1~6演变输出到文件,层序创建二叉树
{
static BTNode *t, *bt, *q;
long x=1;
int i,j;
//1
bt = (BTNode*)malloc(sizeof(BTNode));
bt->data = 0;
for(i=0;i<6;i++){
bt->shuzu[i]=n[i];
}
for(j=0;j<6;j++){//将数组写入已打印队列,以便查找有无重复
record[0][j]=n[j];
}
bt->rchild = bt->lchild = NULL;
que[rear++] = bt;
while(x<GuangduZize & front<rear){
t = que[front];
front++;
//M,left
if(flag){
merge6(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x;
for(i=0;i<6;i++){
q->shuzu[i]=n[i];
}
//flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<6;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->lchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->lchild = NULL;
printf("找到序号为:%d\n",x-1);
break;
}
if(flag){
invert6(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x+1;
for(i=0;i<6;i++){
q->shuzu[i]=n[i];
}
//flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<6;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->rchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->rchild = NULL;
printf("找到序号为:%d\n",x);
break;
}
x+=2;
}
return bt;
}
BTNode* CreateBiTree5(int n[12])//m6,由1~6演变输出到文件,层序创建二叉树
{
static BTNode *t, *bt, *q;
long x=1;
int i,j;
//1
bt = (BTNode*)malloc(sizeof(BTNode));
bt->data = 0;
for(i=0;i<6;i++){
bt->shuzu[i]=i+1;
}
for(j=0;j<6;j++){//将数组写入已打印队列,以便查找有无重复
record[0][j]=j+1;
}
bt->rchild = bt->lchild = NULL;
que[rear++] = bt;
while(x<GuangduZize & front<rear){
t = que[front];
front++;
if(flag){
invert6(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x+1;
for(i=0;i<6;i++){
q->shuzu[i]=n[i];
}
//flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<6;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->rchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->rchild = NULL;
printf("找到序号为:%d\n",x);
break;
}
//M,left
if(flag){
merge6(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x;
for(i=0;i<6;i++){
q->shuzu[i]=n[i];
}
//flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<6;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->lchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->lchild = NULL;
printf("找到序号为:%d\n",x-1);
break;
}
x+=2;
}
return bt;
}
BTNode* CreateBiTree3(int n[12])//m12,由1~12演变输出到文件,层序创建二叉树
{
static BTNode *t, *bt, *q;
long x=1;
int i,j;
//1
bt = (BTNode*)malloc(sizeof(BTNode));
bt->data = 0;
for(i=0;i<12;i++){
bt->shuzu[i]=i+1;
}
for(j=0;j<12;j++){//将数组写入已打印队列,以便查找有无重复
record[0][j]=j+1;
}
bt->rchild = bt->lchild = NULL;
que[rear++] = bt;
while(x<GuangduZize & front<rear){
t = que[front];
front++;
//M,left
if(flag){
merge(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x;
for(i=0;i<12;i++){
q->shuzu[i]=n[i];
}
//flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<12;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->lchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->lchild = NULL;
printf("找到序号为:%d\n",x-1);
break;
}
if(flag){
invert(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x+1;
for(i=0;i<12;i++){
q->shuzu[i]=n[i];
}
//flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<12;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->rchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->rchild = NULL;
printf("找到序号为:%d\n",x);
break;
}
x+=2;
}
return bt;
}
BTNode* CreateBiTree4(int n[12])//m12,由1~12演变输出到文件,层序创建二叉树
{
static BTNode *t, *bt, *q;
long x=1;
int i,j;
//1
bt = (BTNode*)malloc(sizeof(BTNode));
bt->data = 0;
for(i=0;i<12;i++){
bt->shuzu[i]=n[i];
}
for(j=0;j<12;j++){//将数组写入已打印队列,以便查找有无重复
record[0][j]=n[i];
}
bt->rchild = bt->lchild = NULL;
que[rear++] = bt;
while(x<GuangduZize & front<rear){
t = que[front];
front++;
//M,left
if(flag){
merge(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x;
for(i=0;i<12;i++){
q->shuzu[i]=n[i];
}
flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<12;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->lchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->lchild = NULL;
printf("找到序号为:%d\n",x-1);
break;
}
if(flag){
invert(t->shuzu,n);
q = (BTNode*)malloc(sizeof(BTNode));
q->data = x+1;
for(i=0;i<12;i++){
q->shuzu[i]=n[i];
}
flag=findFlag(n);
if(!findSameFlag4(n)){
x+=2;//v3.2版本修复bug
continue;
}else{
for(i=1;i<ShuzuSize;i++){
if(record[i][0]==0){
for(j=0;j<12;j++){
record[i][j]=n[j];
}
break;
}
}
}
t->rchild = q;
q->rchild = q->lchild = NULL;
que[rear++] = q;
}
else
{
t->rchild = NULL;
printf("找到序号为:%d\n",x);
break;
}
x+=2;
}
return bt;
}
void DispBTNode(BTNode *b,FILE* fp){ //以括号表示法输出二叉树
if(b!=NULL){
//printf("\t%6d ",b->data);
fprintf(fp,"\t%6d ",b->data);
for(int i=0;i<6;i++){//12
//printf("%2d ",b->shuzu[i]);
fprintf(fp,"%2d ",b->shuzu[i]);
}
//printf("\r\n");
fprintf(fp,"\n");
if(b->lchild!=NULL || b->rchild!=NULL){
//printf("(");
fprintf(fp,"(");
DispBTNode(b->lchild,fp);
if(b->rchild!=NULL)
//printf(",");
fprintf(fp,",");
DispBTNode(b->rchild,fp);
//printf(")");
fprintf(fp,")");
}
}
}
void DispBTNode2(BTNode *b,FILE* fp){ //以括号表示法输出二叉树
if(b!=NULL){
printf("%d",b->data);
fprintf(fp,"%d",b->data);
//for(int i=0;i<12;i++){
// printf("%2d ",b->shuzu[i]);
// fprintf(fp,"%2d ",b->shuzu[i]);
//}
//printf("\r\n");
//fprintf(fp,"\n");
if(b->lchild!=NULL || b->rchild!=NULL){
printf("(");
fprintf(fp,"(");
DispBTNode2(b->lchild,fp);
if(b->rchild!=NULL)
printf(",");
fprintf(fp,",");
DispBTNode2(b->rchild,fp);
printf(")");
fprintf(fp,")");
}
}
}
void AllPath(BTNode *b){ //采用非递归方法输出从叶子结点到根结点的路径
struct snode{
BTNode *node; //存放当前结点指针
int parent; //存放双亲结点在队列中的位置
}Qu[MaxSize]; //定义顺序队列
int front,rear,p; //定义队头和队尾指针
front=rear=-1; //置队列为空队列
rear++;
Qu[rear].node=b; //根结点指针进入队列
Qu[rear].parent=-1; //根结点没有双亲结点
while(front<rear){ //队列不为空
front++;
b=Qu[front].node; //队头出队列
if(b->lchild==NULL && b->rchild==NULL){ //*b为叶子结点
printf("%d到根结点路径:",b->data);
p=front;
while(Qu[p].parent!=-1){
printf("%d ",Qu[p].node->data);
p=Qu[p].parent;
}
printf("%d\n",Qu[p].node->data);
}
if(b->lchild!=NULL){ //左孩子入队列
rear++;
Qu[rear].node=b->lchild;
Qu[rear].parent=front;
}
if(b->rchild!=NULL){ //右孩子入队列
rear++;
Qu[rear].node=b->rchild;
Qu[rear].parent=front;
}
}
}
void AllPath1(BTNode *b,int path[],int pathlen){ //采用递归方法输出从叶子结点到根结点的路径
int i;
if(b!=NULL){
if(b->lchild==NULL && b->rchild==NULL){ //*b为叶子结点
printf("%d到根结点路径:%d ",b->data,b->data);
for(i=pathlen-1;i>=0;i--)
printf("%d ",path[i]);
printf("\n");
}else{
path[pathlen]=b->data; //将当前结点放入路径中
pathlen++;
AllPath1(b->lchild,path,pathlen); //递归扫描左子树
AllPath1(b->rchild,path,pathlen); //递归扫描右子树
pathlen--;
}
}
}
void LongPath(BTNode *b,int path[],int pathlen,int longpath[],int &longpathlen){ //求最长路径
int i;
if(b==NULL){
if(pathlen>longpathlen){ //若当前路径更长,将路径保存在longpath中
for(i=pathlen-1;i>=0;i--)
longpath[i]=path[i];
longpathlen=pathlen;
}
}else{
path[pathlen]=b->data; //将当前结点放入路径中
pathlen++; //路径长度增1
LongPath(b->lchild,path,pathlen,longpath,longpathlen); //递归扫描左子树
LongPath(b->rchild,path,pathlen,longpath,longpathlen); //递归扫描右子树
pathlen--; //恢复环境
}
}
void DispLeaf(BTNode *b){ //输出叶子结点
if(b!=NULL){
if(b->lchild==NULL && b->rchild==NULL)
printf("%d ",b->data);
else{
DispLeaf(b->lchild);
DispLeaf(b->rchild);
}
}
}
// 在二叉树(并不需要是排序二叉树)中查找value的节点,并返回指向该节点的指针,没找到返回NULL
Bitree getNodeByValue( Bitree root, int data )
{
Bitree pRet = NULL;
if( NULL == root )
{
printf("getNodeByValue func: err -1, NULL==root");
return pRet;
}
if( root->data == data )
{
pRet = root;
return pRet;
}
else
{
Bitree pLeftResult = NULL;
Bitree pRightResult = NULL;
if( root->lchild != NULL )
{
pLeftResult = getNodeByValue( root->lchild, data );
}
if( pLeftResult != NULL ) // 找到了
{
pRet = pLeftResult;
return pRet;
}
if( root->rchild != NULL )
{
pRightResult = getNodeByValue( root->rchild, data );
}
if( pRightResult != NULL ) // 找到了
{
pRet = pRightResult;
return pRet;
}
else
{
return pRet;
}
}
}
//查找从根节点到pNode节点的路径
//返回0表示查找成功,-1表示查找失败
int getNodePathFromRoot1( Bitree root, Bitree pNode, vector<Bitree> &path )
{
int ret = 0;
if( NULL == root || NULL == pNode )
{
//printf("getNodePathFromRoot1 func: err -1, NULL == root || NULL == pNode");
ret = -1;
return ret;
}
if( root == pNode ) // 查找到了
{
path.push_back(root);
return ret;
}
path.push_back(root);
Bitree pleft = root->lchild;
Bitree pright = root->rchild;
int found = -1;
if( pleft != NULL )
{
int ret1 = getNodePathFromRoot1( pleft, pNode, path ); // 从左子树查找
if( 0 == ret1 )
{
ret = ret1;
return ret;
}
}
if( pright != NULL )
{
int ret2 = getNodePathFromRoot1( pright, pNode, path ); // 从右子树查找
if( 0 == ret2 )
{
ret = ret2;
return ret;
}
}
path.pop_back(); // 左右子树都没有找到就弹出当前元素
ret = -1;
return ret; // 返回查找失败的标志
}
int breath_travel(Bitree pRoot,Queue *pQueue)
{
if(!pRoot)
{
return 0;
}
enQueue(pQueue,pRoot);
printf("_______________________\n");
printf("breath begin,enter root:\n");
while(ifEmpty(pQueue)!=0)
{
QNode *qNode = deQueue(pQueue);
//make suer every enQueue Node is not NULL
if(qNode->t_node->lchild!=NULL)
enQueue(pQueue,qNode->t_node->lchild);
if(qNode->t_node->rchild!=NULL)
enQueue(pQueue,qNode->t_node->rchild);
//print the tree node value
printf("%d ",qNode->t_node->data);
}
printf("\n-----------\nbreath end!\n-----------\n");
return 1;
}
void DispBTNode3(BTNode *bt,FILE* fp){ //有问题未完成
static Bitree nNode = NULL;
static vector<Bitree> curPathe;
long len;
long ch;
if(bt!=NULL){
ch=bt->data;
printf("%6d ",ch);
fprintf(fp,"%6d ",ch);
for(int i=0;i<12;i++){//12
fprintf(fp,"%2d ",bt->shuzu[i]);
}
printf("\t");
//得到路径
nNode = getNodeByValue( bt, ch );
getNodePathFromRoot1( bt, nNode, curPathe );
len = curPathe.size();
//for(i = len-1; i >0; --i )
//{
//printf("%c", (curPathe[i]->data)%2==0?'I':'M');
// fprintf(fp,"%c", (curPathe[i]->data)%2==0?'I':'M');
//}
//fprintf(fp,"\t");
for(i = 0; i < len-1; ++i )
{
if(curPathe[i]->data<curPathe[i+1]->data){// & curPathe[i]->data+1!=curPathe[i+1]->data){
fprintf(fp,"%ld ", curPathe[i]->data);
}
}
fprintf(fp,"%ld\t", curPathe[len-1]->data);
for(i = 1; i < len-1; ++i )
{
if(curPathe[i]->data<curPathe[i+1]->data){// & curPathe[i]->data+1!=curPathe[i+1]->data){
fprintf(fp,"%c", (curPathe[i]->data)%2==0?'I':'M');
}
}
fprintf(fp,"%c", (curPathe[len-1]->data)%2==0?'I':'M');
printf("\n");
fprintf(fp,"\n");
if(bt->lchild!=NULL || bt->rchild!=NULL){
DispBTNode3(bt->lchild,fp);
if(bt->rchild!=NULL)
DispBTNode3(bt->rchild,fp);
}
}
}
void DispBTNode4(BTNode *b,FILE* fp){
int i,res;
long ch=0;
Bitree pNode = NULL;
while(ch<GuangduZize){
pNode = getNodeByValue( b, ch );
//while( ch && pNode )
{
//Bitree pNode = getNodeByValue( b, ch );
vector<Bitree> curPath;
//vector<Bitree> path = getNodePathFromRoot( root, pNode, curPath );
res=getNodePathFromRoot1( b, pNode, curPath );
if(res==0){
fprintf(fp,"%ld\n",ch);
long len = curPath.size();
for(i = 0; i < len; ++i )
{
fprintf(fp,"%ld ", curPath[i]->data);
}
fprintf(fp,"\t");
for(i = 1; i < len; ++i )
{
fprintf(fp,"%c", (curPath[i]->data)%2==0?'I':'M');
}
fprintf(fp,"\n");
//ch = NULL;
}
}
ch++;
}
}
void test(BTNode *b){
int i;
Bitree pNode = NULL;
while(1){
//char ch=getchar();
long ch;
printf("请输入序号:");
fprintf(fp,"请输入序号:");
scanf("%ld",&ch);
fprintf(fp,"%ld\n",ch);
pNode = NULL;
pNode = getNodeByValue( b, ch );
while( ch && pNode )
{
//Bitree pNode = getNodeByValue( b, ch );
vector<Bitree> curPath;
//vector<Bitree> path = getNodePathFromRoot( root, pNode, curPath );
getNodePathFromRoot1( b, pNode, curPath );
long len = curPath.size();
for(i = 0; i < len; ++i )
{
printf("%ld ", curPath[i]->data);
fprintf(fp,"%ld ", curPath[i]->data);
}
printf("\t");
fprintf(fp,"\t");
for(i = 1; i < len; ++i )
{
printf("%c", (curPath[i]->data)%2==0?'I':'M');
fprintf(fp,"%c", (curPath[i]->data)%2==0?'I':'M');
}
printf("\r\n");
fprintf(fp,"\r\n");
ch = NULL;
}
fflush(fp);
}
}
int main(){
static BTNode *b;
//FILE* fp;
static int path[MaxSize],longpath[MaxSize];
long i,longpathlen=0;
int n[12];
flag=1;
sameflag=1;
fp=fopen("D:\\123.txt","w+");
//CreateBTNode(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
//CreateBTNode(b,"1(2(4(7(12(19(28(39(52(67,68(84(101,102(117,118(131,132(143,144(161,162(169,170(175,176(179,180)))))))))),53(69(85,86(103,104(119,120(133,134(145,146(163,164(171,172(177,178)))))))))),40(54(70,71(87,88(105,106(121,122(135,136(147,148(165,166(173,174)))))))))),29(41(55,56(72,73(89,90(107,108(123,124(137,138(149,150(167,168)))))))))),20(30(42,43(57,58(74,75(91,92(109,110(125,126(139,140(151,152)))))))))),13(21(31,32(44,45(59,60(76,77(93,94(111,112(127,128(141,142)))))))))),8(14(22,23(33,34(46,47(61,62(78,79(95,96(113,114(129,130)))))))))),5(9(15,16(24,25(35,36(48,49(63,64(80,81(97,98(115,116)))))))))),3(6(10,11(17,18(26,27(37,38(50,51(65,66(82,83(99,100))))))))))");
//CreateBTNode(b,"1(3(5(7(9(11(13(15(17(19(21(,22),20),18),16),14),12),10),8),6),4),2(23(25(27(29(31(33(35(37(39(41(,42),40),38),36),34),32),30),28),26),24)))");
//1(3(5(7(9(11(13(15(17(19(21(,22),20),18),16),14),12),10),8),6),4),2(23(25(27(29(31(33(35(37(39(41(,42),40),38),36),34),32),30),28),26),24)))
//CreateBTNode1(b);//先序创建二叉树
//CreateBTNode2(b);
//CreateBTNode3(b);
printf("请不重复且随机的输入1~12:\n");
fprintf(fp,"请不重复且随机的输入1~12:\n");
fprintf(fp,"eg:1 2 3 4 5 6 7 8 9 10 11 12\n");
fflush(fp);
for(i=0;i<6;i++)//12
{
scanf("%d",&n[i]);
}
//CreateBTNode4(b,n);
//CreateBTNode5(b,n);
//CreateBTNode6(b,n);
//CreateBTNode7(b,n);
//b=CreateBiTree(n);//层序创建二叉树,更好,输入打乱后的数,排列成1~6
b=CreateBiTree2(n);//输入1~6,生成txt文件用于比较
//b=CreateBiTree3(n);//输入1~12,用于比较
printf("二叉树b:\n");
fprintf(fp,"二叉树b:\n");
DispBTNode(b,fp);
DispBTNode4(b,fp);
printf("\n\n");
printf("文件输出完毕!位置为D:\\123.txt\n");
//printf("b的叶子结点:");DispLeaf(b);printf("\n\n");
//printf("AllPath:\n");AllPath(b);printf("\n");
//printf("AllPath1:\n");AllPath1(b,path,0);printf("\n");
//LongPath(b,path,0,longpath,longpathlen);
//printf("第一条最长路径长度:%d\n",longpathlen);
//printf("第一条最长路径:");
//for(i=longpathlen-1;i>=0;i--)
// printf("%d ",longpath[i]);
//printf("\n");
fflush(fp);
/*
Bitree pNode = NULL;
while(1){
//char ch=getchar();
long ch;
printf("请输入序号:");
fprintf(fp,"请输入序号:");
scanf("%ld",&ch);
fprintf(fp,"%ld\n",ch);
pNode = getNodeByValue( b, ch );
while( ch && pNode )
{
//Bitree pNode = getNodeByValue( b, ch );
vector<Bitree> curPath;
//vector<Bitree> path = getNodePathFromRoot( root, pNode, curPath );
getNodePathFromRoot1( b, pNode, curPath );
long len = curPath.size();
for(i = 0; i < len; ++i )
{
printf("%ld ", curPath[i]->data);
fprintf(fp,"%ld ", curPath[i]->data);
}
printf("\t");
fprintf(fp,"\t");
for(i = 1; i < len; ++i )
{
printf("%c", (curPath[i]->data)%2==0?'I':'M');
fprintf(fp,"%c", (curPath[i]->data)%2==0?'I':'M');
}
printf("\r\n");
fprintf(fp,"\r\n");
ch = NULL;
}
fflush(fp);
}*/
test(b);
fclose(fp);
return 0;
}
代码中为了简化调试,我曾使用过1-6,所以如果运行异常,可以尝试1-6。
java版本在处理内存和二叉树上更加简单:
BinaryTree.java
package javab;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class BinaryTree {
final static int MAXSIZE = 2000000;
final static int GUANGDUSIZE = 80;
final static int SHUZUSIZE = 100;
static int record[][] = new int[SHUZUSIZE][4];
static int flag;//find " 1 2 3 4 5 6 7 8 9 10 11 12"
TreeNode root;
public BinaryTree() {
root = null;
}
public int merge(int[] input, int[] output){
output[0]=input[0];
output[1]=input[11];
output[2]=input[1];
output[3]=input[10];
output[4]=input[2];
output[5]=input[9];
output[6]=input[3];
output[7]=input[8];
output[8]=input[4];
output[9]=input[7];
output[10]=input[5];
output[11]=input[6];
return 1;
}
public int invert(int[] input, int[] output){
int temp,k=0;
merge(input, output);
while(k<6)//12/2
{
temp=input[k];
output[k]=input[11-k];//12-k-1
output[11-k]=temp;//12-k-1
k++;
}
return 1;
}
public int findFlag(int n[]){
if(flag==0 | (n[0]==1 && n[1]==2 && n[2]==3 && n[3]==4 && n[4]==5)){
return 0;
}else{
return 1;
}
}
public int findSameFlag(int[] n){
for(int i=0;i<SHUZUSIZE;i++){
//fprintf(fp,"%3d\t%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d%2d\n",i,n[0],n[1],n[2],n[3],n[4],n[5],record[i][0],record[i][1],record[i][2],record[i][3],record[i][4],record[i][5]);
if(n[0]==record[i][0] && n[1]==record[i][1] && n[2]==record[i][2] && n[3]==record[i][3] && n[4]==record[i][4]){
return 0;
}
}
return 1;
}
//层序创建树
//http://moonmonster.iteye.com/blog/2249490
public void builderTree(int[] n) {
TreeNode[] tree = new TreeNode[100];
int[] tmpsz = new int[12];
int[] tmpsz2=new int[12];
int index = 0;
while (index<GUANGDUSIZE) {
TreeNode temp = null;
if (index == 0) {
root = new TreeNode(index+1, n);
//root.shuzu = n;
tree[index] = root;
//for(int i:tree[index].shuzu){
// System.out.println(i);
//}
} else {
if (index % 2 == 0) {
tmpsz2=tree[index/2-1].shuzu;
invert(tmpsz2, tmpsz);
if(findSameFlag(tmpsz)==0){
index++;
continue;
}else{
for(int i=1;i<SHUZUSIZE;i++){
if(record[i][0]==0){
record[i]=n;
break;
}
}
temp = new TreeNode(index+1, tmpsz);
//temp.shuzu = tmpsz;
tree[index] = temp;
tree[index / 2-1].rightChild = temp;
}
} else {
System.out.println("tree");
tmpsz2=tree[index/2].shuzu;
for(int i=0;i<12;i++){
System.out.print(tmpsz2[i]+" ");
}
merge(tmpsz2,tmpsz);
System.out.println("tmpsz");
for(int i=0;i<12;i++){
System.out.print(tmpsz[i]+" ");
}
if(findSameFlag(tmpsz)==0){
index++;
}else{
for(int i=1;i<SHUZUSIZE;i++){
if(record[i][0]==0){
record[i]=n;
break;
}
}
temp = new TreeNode(index+1, tmpsz);
//temp.shuzu = tmpsz;
System.out.println("");
tree[index] = temp;
tree[index / 2].leftChild = temp;
}
}
}
index++;
}
}
//层序输出
//https://blog.youkuaiyun.com/snow_7/article/details/51815787
public void levelIterator(TreeNode root)
{
if(root == null)
{
return ;
}
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
TreeNode current = null;
queue.offer(root);//将根节点入队
while(!queue.isEmpty())
{
current = queue.poll();//出队队头元素并访问
//System.out.print(current.data +"-->");
System.out.print(current.data +" ");
for(int i=0;i<12;i++){
System.out.print(current.shuzu[i]+" ");
}
System.out.println("");
if(current.leftChild != null)//如果当前节点的左节点不为空入队
{
queue.offer(current.leftChild);
}
if(current.rightChild != null)//如果当前节点的右节点不为空,把右节点入队
{
queue.offer(current.rightChild);
}
}
System.out.println("");
}
//求根节点到叶子节点路径
//https://blog.youkuaiyun.com/xiezongsheng1990/article/details/79574892
public List<String> binaryTreePaths(TreeNode root) {
List<String> list=new ArrayList<String>();
Queue<TreeNode> qNode=new LinkedList<TreeNode>();
Queue<String> qStr=new LinkedList<String>();
if (root==null) return list;
qNode.add(root);
qStr.add("");
while(!qNode.isEmpty()) {
TreeNode curNode=qNode.remove();
String curStr=qStr.remove();
if (curNode.leftChild==null && curNode.rightChild==null) list.add(curStr+curNode.data);
if (curNode.leftChild!=null) {
qNode.add(curNode.leftChild);
qStr.add(curStr+curNode.data+"->");
}
if (curNode.rightChild!=null) {
qNode.add(curNode.rightChild);
qStr.add(curStr+curNode.data+"->");
}
}
return list;
}
/*
public BinaryTree(int data){
setTree(data);
}
public BinaryTree(int data,BinaryTree left,BinaryTree right){
setTree(data,left,right);
}
void setTree(int data){
root=new TreeNode(data);
}
void setTree(int data,BinaryTree left,BinaryTree right){
root=new TreeNode(data);
if(left!=null){
root.setleftChild(left.root);
}
if(right!=null){
root.setrightChild(right.root);
}
}
*/
}
Tree.java
package javab;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.List;
import java.util.Scanner;
public class Tree {
final static int MAXSIZE = 2000000;
final static int GUANGDUSIZE = 80;
final static int SHUZUSIZE = 100;
static int record[][] = new int[SHUZUSIZE][4];
static int flag;//find " 1 2 3 4 5 6 7 8 9 10 11 12"
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
//BinaryTree tree1=create();
File f = new File("output.txt");
FileOutputStream fileOutputStream = new FileOutputStream(f,false);
//true可以追加到文件output.txt的末尾,没有true 每次新建一个output.txt
PrintStream printStream = new PrintStream(fileOutputStream);
// 重新分配“标准”输出流
System.setOut(printStream);
BinaryTree tree1 = new BinaryTree();
Scanner sc = new Scanner(System.in);
int[] input = new int[12];
for(int i=0;i<12;i++){
input[i]=Integer.parseInt(sc.next());
}
tree1.builderTree(input);
tree1.levelIterator(tree1.root);
List<String> list = tree1.binaryTreePaths(tree1.root);
for(String str:list){
System.out.println(str);
}
// int[] a=new int[12];
// int[] b=new int[12];
// for(int i=0;i<12;i++){
// a[i]=i+1;
// }
// tree1.invert(a, b);
// tree1.merge(b, a);
// for(int i=0;i<12;i++){
// System.out.println(a[i]);
// }
}
}
Treenode.java
package javab;
//https://www.cnblogs.com/MISSCHEN/p/3788093.html
public class TreeNode {
//final static int MAXSIZE = 2000000;
//final static int GUANGDUSIZE = 80;
//final static int SHUZUSIZE = 100;
//static int flag;
int data;
int[] shuzu = new int[12];
TreeNode leftChild,rightChild,next;
public TreeNode(int data,int[] shuzu){
this.data=data;
this.shuzu = shuzu;
}
public TreeNode(int data,TreeNode left,TreeNode right){
leftChild=left;
rightChild=right;
}
public int getdata(){
return data;
}
public void setleftChild(TreeNode left){
leftChild=left;
}
public void setrightChild(TreeNode right){
rightChild=right;
}
}
这个项目是想研究魔方中的最短路径和有哪些路径是重复的。在数学中这属于群论的问题(散在单群)。这是个简易版的解魔方程序,如果刚入门解不了魔方,可以先解这个,有了思路可以尝试更复杂的二阶,三阶魔方。