首先因为个人原因前段时间在解一个数独,因为很难解不出来,再加上我王哥的启发,就想的写个程序来解决这类问题,于是就有了这篇文章。。。还有最近在学数据结构,里面很多东西用的都是比较繁琐的解决办法,比如链式存储,链栈之类的,但这样思路比较清晰。

1.程序大致思路

将数组元素全部初始化为0,然后将空位的行列入栈,然后开始给栈顶元素的空位逐步++;每次++都要判断这个数填在这个空位合不合适,合适的话入栈下一个元素,否则就出栈,这样就回溯到了上一个空位,继续++,这样当最后一个空位解决后,就出现了数独的第一个解,然后解决多解的话,将此时的栈顶元素出栈,给栈顶元素++,将指针指向上一个空位,利用goto语句来实现数独的多解;

2.代码改进思路

如果不用数据结构的链栈知识的话,可将栈直接简化成 s[M],top来进行出入栈操作,这样代码的行数将大大减少。

3.程序功能:

可以进行数独的解(多解)。

如果出现解比较多的数独,机器运行时间比较长;

4.关键代码解析

 利用while进入循环(注:因为循环条件是p->next!=NULL,如果循环条件是p!=NULL的话,当指针p指向链表的最后一个元素的话,进入这条语句,最后一个空位肯定合适,所以指针p还会往后移一个,所以就找不到p的位置了,也就无法回溯(p=p->before);所以解决办法就是p->next!=NULL,并且存链表的时候在末端多存一个垃圾值);循环里面入栈,然后进行do while先从0++一次,然后通过qualified函数判断空位能不能填这个数字,能的话返回0跳出循环,不能继续do while。然后通过if判断,是通过怎样的方式跳出循环的:if跳出循环后a[row1][list1]<10就证明,这个数字可以填在此时的空位,则指针往后移动,下一个入栈,else则说明1-9没有合适的数字填到这个空位,则给这个空位初始化为0,出栈,将指针回调,继续循环。

5.程序源代码:

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>int a[9][9]={0};typedef struct nood
{int row;int list;struct nood *next;
}LinkList;typedef struct Stack             //申明一个栈
{LinkList *top;LinkList *bottom;
}LinkStack;typedef struct nood_1            // 申明一个双链表
{int row;int list;struct nood_1 *next;struct nood_1 *before;
}DulLinkList;void init_Stack(LinkStack *s)   // 栈的初始化
{s->top=(LinkList *)malloc(sizeof(LinkList));s->bottom=s->top;s->top->next=NULL;
}DulLinkList *init_DulLinkList(DulLinkList *head)   //双链表的初始化
{head=(DulLinkList *)malloc(sizeof(DulLinkList));head->next=NULL;head->before=NULL;return head;
}void push_Stack(LinkStack *s,int row1,int list1)   //入栈操作
{LinkList *p;p=(LinkList *)malloc(sizeof(LinkList));p->row=row1;p->list=list1;p->next=s->top;s->top=p;
}void push_DulLinkList(DulLinkList *head,int row1,int list1)   //把数独空位的行列保存到双链表里方便操作
{DulLinkList *p,*r;r=head;while(r->next!=NULL){r=r->next;}p=(DulLinkList *)malloc(sizeof(DulLinkList));p->row=row1;p->list=list1;r->next=p;p->before=r;p->next=NULL;
}int empty_Stack(LinkStack *s)                 //栈的判空
{if(s->top==s->bottom)return 1;else return 0;
}void pull_Stack(LinkStack *s,int *row1,int *list1)   // 出栈操作
{LinkList *p;p=s->top;*row1=p->row;*list1=p->list;s->top=p->next;free(p);
}void print_shudu()                      //打印此时数独的结果
{int i,j;printf("数独结果为:\n");for(i=0;i<9;i++){for(j=0;j<9;j++){if(a[i][j]==0){printf("|   ");  }elseprintf("|%2d ",a[i][j]);if(j==8)printf("|");}printf("\n\n");}
}int qualified(int x,int row,int list)         //判断填的数字在这个空位的 行、 列 、九宫格是否合适
{                                               int i,j,f1,f2;for(i=0;i<row;i++)if(a[i][list]==x)return 1;for(i=row+1;i<9;i++)if(a[i][list]==x)return 1;for(i=0;i<list;i++)if(a[row][i]==x)return 1;for(i=list+1;i<9;i++)if(a[row][i]==x)return 1;f1=row-row%3;f2=list-list%3;for(i=f1;i<f1+3;i++){for(j=f2;j<f2+3;j++){if((i!=row)||(j!=list)){if(a[i][j]==x)return 1;}}}return 0;
}int jie(LinkStack *s,DulLinkList *head)             //利用回溯法开始对数独的空位逐个解决
{int i,j,row1,list1,flag=1,c1,c2;DulLinkList *p,*q;q=head;p=head->next;
f1: while(p->next!=NULL){push_Stack(s,p->row,p->list);row1=s->top->row;list1=s->top->list;do{a[row1][list1]++;}while(a[row1][list1]<10 && qualified(a[row1][list1],row1,list1));if(a[row1][list1]<10){p=p->next;}else{a[row1][list1]=0;pull_Stack(s,&c1,&c2);p=p->before;}}if(p!=q){printf("这个数独的第%d个解为:\n",flag);print_shudu();}if(p==q)return 0;else{pull_Stack(s,&c1,&c2);a[c1][c2]++;p=p->before;flag++;goto f1;}
}int main()
{LinkStack S;DulLinkList *L;int i,j;init_Stack(&S);L=init_DulLinkList(L);printf("please enter a sudoku :\n");for(i=0;i<9;i++){for(j=0;j<9;j++){scanf("%d",&a[i][j]);if(a[i][j]==0){push_DulLinkList(L,i,j);          }}}push_DulLinkList(L,-1,-1);system("CLS");print_shudu();if(jie(&S,L)==0)printf("这个数独无解\n");
} 

6.程序待解决的问题:

出现无解,他会直接退出程序,并不会提示,程序的时间复杂度也比较高

7.数独提供样例:

3 0 6 4 5 1 8 7 9
0 4 5 7 0 9 2 0 0
7 0 9 2 0 0 1 4 5
0 0 3 5 4 7 6 9 0
0 0 0 0 9 0 0 1 2
6 0 8 0 2 3 4 0 0
5 0 1 0 0 2 9 6 4
8 6 4 0 0 5 7 2 3
9 7 2 3 6 4 0 8 0 0 0 0 5 0 0 9 2 7
2 3 0 1 7 9 0 6 0
0 0 0 0 4 0 0 3 5
1 0 3 4 0 0 0 0 0
0 0 0 0 0 8 0 0 0
8 0 0 0 0 2 0 0 0
0 1 4 7 2 0 0 0 6
6 0 0 9 3 1 7 0 0
0 7 2 8 0 4 0 0 00 0 0 0 0 0 0 0 0
0 8 0 0 7 0 0 3 0
0 0 0 0 0 0 0 0 0
7 0 0 0 1 0 0 0 3
0 0 0 0 0 6 0 0 0
0 0 2 0 0 0 4 0 0
0 0 0 0 5 0 0 0 0
0 4 0 0 6 0 0 9 0
6 0 0 0 0 0 3 0 0

这里特别感谢我王哥的帮助,没他就没这些思路和BUG的解决,程序也有太多问题,如果有大佬发现问题或者有更好的解决办法的话滴滴我,感谢感谢!!!

数独解、多解(数据结构、栈、回溯法)相关推荐

  1. web api 数独 求解代码 使用穷举回溯法

    先看效果 首先是html代码 <!DOCTYPE html> <html lang="zh-cn" data-ng-app="app"> ...

  2. LV算法和回溯法结合解n后问题

    我的算法作业:n=12 ~ 20时,求出较优的stopVegas值.(也就随机放置几个皇后比较好的问题). 解答:(VC6.0下调试通过,可能某些统计数据的计算部分,有不太妥当的地方,贴出来也就是有高 ...

  3. 【算法分析】实验 4. 回溯法求解0-1背包等问题

    目录 实验内容 实验目的 实验结果 步骤1:描述与分析 步骤2:策略以及数据结构 步骤3 步骤4 步骤5 步骤6 实验总结 实验内容 本实验要求基于算法设计与分析的一般过程(即待求解问题的描述.算法设 ...

  4. 回溯法遵循深度优先吗_回溯算法(一)

    一.什么是回溯算法 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就"回溯"返回,尝试别的路径.许多复杂的,规模较大的问题 ...

  5. 回溯法基本思想_回溯算法(一)

    一.什么是回溯算法 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就"回溯"返回,尝试别的路径.许多复杂的,规模较大的问题 ...

  6. java背包算法回溯法_【算法分析】实验 4. 回溯法求解0-1背包等问题

    [TOC] 实验内容 本实验要求基于算法设计与分析的一般过程(即待求解问题的描述.算法设计.算法描述.算法正确性证明.算法分析.算法实现与测试),通过回溯法的在实际问题求解实践中,加深理解其基本原理和 ...

  7. 回溯法 —— 求解0/1背包问题(剪枝)

    0/1背包问题 题目描述: 有n个重量分别为w1,w2,-,wn的物品(物品编号为1~n),它们的价值分别为v1,v2,-,vn,给定一个容量为W的背包.设计从这些物品中选取一部分物品放入该背包的方案 ...

  8. 回溯法之活动安排问题

    1.问题:假设有一个需要使用某一资源的n个活动所组成的集合S,S={1,-,n}.该资源任何时刻只能被一个活动所占用,活动i有一个开始时间bi和结束时间ei(bi<ei),其执行时间为ei-bi ...

  9. educoder算法设计与分析 实验五回溯法

    实验五 回溯法 第1关:排列 第2关:子集合 第3关:TSP问题 第4关:n皇后问题 第5关:0-1背包 第1关:排列 题目描述: 1.设计算法从前m个大写字母(m≤26)种取出n个字母的所有排列(组 ...

  10. 回溯法—子集树与排列树

    回溯法有"通用解题法"之称.用它可以系统地搜索问题的所有解.回溯法是一个既带有系统性又带有跳跃性的搜索算法. 在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深 ...

最新文章

  1. Discuz!X3.1数据库的操作(三)
  2. cent6.8 nginx php,CentOS 6.8 安装Nginx
  3. truffle和remix区别
  4. ARM开发6.3.2 基础实训( 2 ) 单个数码 LED 的显示输出系统设计( 2 )--LPC21XX
  5. 2021财经直播系统 H5网页直播 大区直播间源码
  6. devcon-计算机硬件设备的禁用与启动说明
  7. 802.11无线wifi协议学习(二)
  8. 一款非常好用的日期插件(强烈推荐)
  9. 设计一套前端项目组织结构
  10. Eureka 源码解析 —— Eureka-Server 集群同步
  11. 表白生日祝福和3D表白相册
  12. 速记混淆矩阵中的FP、FN、FP、TN
  13. 配置类不加@Configuration竟然也可以注册bean
  14. Android_版本对应
  15. 扫雷游戏软件测试,暑期社会实践 | 扫雷游戏的测试完善及总结
  16. python mypy类型检查_Python 类型检查指南
  17. 2023CUPT第七题 法拉第波 思路和解法
  18. Blockchain技术之区块链的概念和起源以及区块链的运行方式、发展前景和应用领域分析
  19. 让网站更新快照的方法
  20. matlab平均值消噪声

热门文章

  1. Golang面向对象之-类
  2. GEP基因表达式编程
  3. 从零开始学习SEO的基础概念
  4. PV-1033/PV-1233/EVP-M33插装式压力补偿流量阀比例放大器
  5. 名词用作动词举例_英语中名词做动词用的55个例句
  6. python使用Elasticsearch对wikipedia的数据进行检索(详细流程)
  7. web课程设计网页规划与设计 :旅游景点网站设计——西安(20页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 HTML静态网页作业
  8. uboot启动流程详细分析(基于i.m6ull)
  9. JAVA计算机毕业设计医院药品管理系统Mybatis+源码+数据库+lw文档+系统+调试部署
  10. 整理: 显示面板行业英文简称解析