C语言深搜—数字全排列

Python026

C语言深搜—数字全排列,第1张

自己可以用单步调试。。要学会自己调试啊!要不有的东西不是文字就能说清的!不会上网查,或找别人教 #if(1) //自己可以用单步调试。。 #include <stdio.h> #include <stdlib.h>int n//定义全局变量 整形n int used[100],a[100]//定义全局变量数组 整形used和a数组 void dfs(int i) //声明dfs()函数 { int c,k//定义局部变量 整形c,k if(i>n) //判断,传送过来的i和n判断,没有看到赋值给n啊!赋值给n啊 { for(k=1k<n+1k++) //循环输出数组a数值 printf("%d ",a[k]) printf("\n") return } for(k=1k<=nk++) //循环 { if(used[k]==0) //判断条件是否成立,成立运行以下代码 { used[k]=1//把1赋值给used[1] a[i]=k//a[1]=1,刚才main函数的dfs(),形参1传送给dfs函数,所以i是1 dfs(i+1) //递归了,又调试这个函数,形参为2了, //因为i+1 ,1+1=2 (*^__^*) 嘻嘻,没地方写,提取出来看下面的把 used[k]=0 } } } int main() //main函数 { int j//定义局部变量 整形j memset(a,0,sizeof(a))//把a数组内的数值定为0 memset(used,0,sizeof(used))//一样 scanf("%d",&n)//接受输入整型给n dfs(1)//把1形参传送给dfs函数,跳到dfs函数内部,看声明dfs()的部分 system("PAUSE")//防止程序一闪而过 return 0//返回值 0 } /* for(k=1k<=nk++) //形参为2了,刚才那个i与n判断不说了 { if(used[k]==0) //判断条件是否成立,成立运行以下代码 { used[k]=1//把1赋值给used[1],还是传给used[1] a[i]=ka[2]=1 dfs(i+1)//形参为3了,再从dfs()看起一直下去,因为没有停止的条件 //它一直下去。。 used[k]=0//不会执行这句的 } } */ #endif()

本质上是一样的。

个人对回溯有两种理解。

第一种理解:回溯就是以非递归实现的深搜,这样的话,回溯就属于深搜。

第二种理解:回溯过程,是深搜过程中的一个子过程。

例如:

void Dfs(int t)

{

……

if (Ok()) //可行性判断

{

Change_togo() //搜索前的标记及修改

Dfs(i+1)//深搜下一层

Change_back() //将标记和修改的值还原

}

}

在这个深搜过程中,Change_back()这个还原的子过程,就可以称为回溯过程。

一般的深搜都带回溯,但是没有回溯的深搜都是好深搜(一次就做完了,复杂度大大的低)

这是用邻接表创建的一个图

实现了广度和深度遍历

希望能帮助你

#include <iostream>

using namespace std

#define MaxSize 50

struct ArcNode // 保存结点后面的所连边对应的点

{

int adjvex

struct ArcNode * nextarc

}

// 用来存放一个节点的结构体,存放首节点,后面定义的是一个结构体数组

struct Vnode

{

int data

struct ArcNode * firstarc

}

int m,n,v

void creatgraph(struct Vnode A[MaxSize])// 创建图

void dfs(struct Vnode A[MaxSize])// 深搜

void bfs(struct Vnode A[MaxSize])// 广搜

int main()

{

struct Vnode AdjList[MaxSize]

int cord

do

{

cout<<" 主菜单"<<endl

cout<<" 1 建立无向图的邻接表"<<endl

cout<<" 2 按深度遍历图"<<endl

cout<<" 3 按广度遍历图"<<endl

cout<<" 4 结束程序运行"<<endl

cout<<"------------------------------"<<endl

cout<<" 请输入你的选择1 ,2 ,3 ,4:"<<endl

cin>>cord

switch(cord)

{

case 1:creatgraph(AdjList)break

case 2:dfs(AdjList)break

case 3:bfs(AdjList)break

case 4:exit(0)

}

}while(cord <= 4)

return 0

}

void creatgraph(struct Vnode A[MaxSize]) //创建图

{

int i,j,k

struct ArcNode *p

cout<<" 输入边和点的个数:"<<endl

cin>>m>>n// m代表边的个数 ,n代表顶点个数

for(k=0k<nk++) // 首先对邻接表的所有顶点初始化

{

A[k].data = k+1

A[k].firstarc = NULL

}

for (k=0k<mk++) // 输入边,并插入到邻接表

{

cout<<" input arc:"<<endl

cin>>i>>j// 这代表一条无向边,顶点i与顶点j相连

p = (struct ArcNode *)malloc(sizeof(struct ArcNode))

p->adjvex = j

p->nextarc = A[i-1].firstarc

A[i-1].firstarc=p

p = (struct ArcNode *)malloc(sizeof(struct ArcNode))

p->adjvex = i

p->nextarc = A[j-1].firstarc

A[j-1].firstarc=p

}

cout<<endl

for(k=0k<nk++)// 输出邻接表

{

cout<<" vex"<<A[k].data<<" arc is:"

p=A[k].firstarc

while(p)

{

cout<<p->adjvex<<" "

p=p->nextarc

}

cout<<endl

}

}

void dfs(struct Vnode A[MaxSize])

{

struct ArcNode *p, *ar[MaxSize]

int x,i,y,top=-1

int visited[MaxSize]

for(i = 0 i <n i++) visited[i] = 0// 这个数组用于代表这个节点是否被遍历过

cout<<"input x of start vex"<<endl

cin>>x// 输入从哪个节点开始遍历

cout<<x

visited[x-1]=1// 首先根节点被发现

p=A[x-1].firstarc// 然后要遍历的是根节点的邻接点

while( (p) || top>=0) // 直到栈为空,并且没有邻接点就退出循环

{

if(!p) // 出栈

{

p = ar[top]

top--

}

y = p->adjvex

if(visited[y-1] == 0)

{

visited[y-1] = 1// 被发现

cout<<" ->"<<y

p = p->nextarc

if(p) {top++ar[top] = p} // 入栈

p=A[y-1].firstarc

}

else

p=p->nextarc

}

}

void bfs(struct Vnode A[MaxSize])

{

struct ArcNode *p

int x,i,y,front=-1,rear=-1,ar[MaxSize],visited[MaxSize]

for(i=0i<ni++) // 这个数组用于代表这个节点是否被遍历过

visited[i]=0

cout<<"input x"<<endl

cin>>x// 代表从哪个节点开始遍历

cout<<x

visited[x-1]=1//代表x的结点被发现

p=A[x-1].firstarc// x被发现之后就遍历x的邻接点

while( (p) || (front!=rear)) // 如果队列为空,并且这个结点没有了邻接点则退出循环

{

if (!p) // 这个当p的邻接点全部入队之后进入这句

{

front++//队列的队首元素的下标往下偏移

y=ar[front]//首先y出队,即去队首元素

p=A[y-1].firstarc//之后就要遍历y的邻接点了

}

y=p->adjvex//取p的数据域

if(visited[y-1] == 0)

{

visited[y-1]=1

cout<<" ->"<<y

rear++//把p的邻接点全部入队,知道遍历到p没有邻接点为止

ar[rear]=y

}

p=p->nextarc

}

}