IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数独解、多解(数据结构、栈、回溯法) -> 正文阅读

[数据结构与算法]数独解、多解(数据结构、栈、回溯法)

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

? ? ? ? ? ? ? ?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("|   ");	
			}
			else
				printf("|%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 0


0 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的解决,程序也有太多问题,如果有大佬发现问题或者有更好的解决办法的话滴滴我,感谢感谢!!!

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-10 12:39:06  更:2021-11-10 12:39:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:31:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码