算法学习笔记 二叉树和图遍历—深搜 DFS 与广搜 BFS

时间:2014-08-24 12:58:32   收藏:0   阅读:8475

图的深搜与广搜

马上又要秋招了,赶紧复习下基础知识。这里复习下二叉树、图的深搜与广搜。从图的遍历说起,图的遍历方法有两种:深度优先遍历(Depth First Search), 广度优先遍历(Breadth First Search),其经典应用走迷宫、N皇后、二叉树遍历等。遍历即按某种顺序访问“图”中所有的节点,顺序分为:

对于深搜,由于递归往往可以方便的利用系统栈,不需要自己维护栈,所以通常实现比较简单。而对于广搜,则需要自己维护一个队列,且由于队列大小未知,底层存储的物理结构采用链式存储。

【文章地址为:http://blog.csdn.net/thisinnocence】


二叉树概念和性质

二叉树是每个节点最多有两个子树的树结构,常被用于实现二叉查找树和二叉堆。在图论中,二叉树定义是一个连通的无环图,并且每一个顶点的度不大于2。二叉树和树有很多相似之处,但并不是树的特殊情形,主要有以下三点主要差别:

  1. 树中结点的最大度数没有限制,而二叉树结点的最大度数为2;
  2. 树的结点无左、右之分,而二叉树的结点有左、右之分;
  3. 树的结点个数至少为1,而二叉树的结点个数可以为0
树的一些相关概念:
二叉树的重要的性质:

小实验(C 实现)

这里首先用一个数组生成一个完全二叉树(链式存储), 然后深搜用前序遍历,广搜借助自己实现的一个队列(链式存储)来进行,图如下所示:

bubuko.com,布布扣

代码为:
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
	int data;
	struct Node * left;
	struct Node * right;
} BitNode, *BiTree;

typedef BiTree QElemType;  // 定义队列元素类型

typedef struct QNode {
	QElemType data;   // 存放树节点指针
	struct QNode *next;
} QNode, *QueuePtr;  // 队列节点和节点指针

typedef struct LinkQueue {
	QueuePtr front, rear;
} LinkQueue; // 队列前后指针: 队首,队尾

/* 初始化队列  */
int InitQueue(LinkQueue *Q) {
	QueuePtr s = (QueuePtr) malloc(sizeof(QNode));
	if (!s)	return 0;
	Q->front = s;
	Q->rear = s;
	return 1;
}

/* 入队 */
int EnQueue(LinkQueue *Q, QElemType e) {
	if (e == NULL)	return 0;
	QueuePtr s = (QueuePtr) malloc(sizeof(QNode));
	if (!s) return 0;
	s->data = e;
	s->next = NULL;
	Q->rear->next = s;
	Q->rear = s;
	return 1;
}

/* 出队 */
int DeQueue(LinkQueue *Q, QElemType *e) {
	if (Q->front == Q->rear) {
		return 0;
	} // 首位指针相等,队列空,出队失败
	QueuePtr p;
	p = Q->front->next; // 头结点不放数据,其后继结点作为队首,出队
	*e = p->data;
	Q->front->next = p->next; // 队首指针后移一个节点
	if (Q->rear == p) {
		Q->rear = Q->front;
	} // 尾指针如果指向的是头结点后第一个节点,则令其指向队首指针。 即队列只有一个数据节点的情况
	free(p);
	return 1;
}

/* 利用数组 a 创建二叉树,递归的编写技巧在于设计好函数接口 */
void CreateTree(BiTree *bt, int a[], int len, int index) {
	if (index > len - 1)
		return;
	(*bt) = (BiTree) malloc(sizeof(BitNode));   // 指针变量初始化堆区的内存,c 用 malloc 函数
	(*bt)->data = a[index];
	(*bt)->left = NULL;   //  不能能省略,当其为叶节点时,指针域为 NULL,而且常作为程序判断条件
	(*bt)->right = NULL;
	CreateTree(&((*bt)->left), a, len, 2 * index + 1);
	CreateTree(&((*bt)->right), a, len, 2 * index + 2);
}

/* 前序遍历二叉树 , 属于深度优先遍历 DFS */
void PreOrderTraverse(BiTree bt) {
	if (bt == NULL)
		return;
	printf("%d ", bt->data); // 操作节点数据
	PreOrderTraverse(bt->left);
	PreOrderTraverse(bt->right);
}

/* 按层遍历,即广度优先遍历 BFS */
void BFSTraverse(BiTree bt) {
	LinkQueue *Q = (LinkQueue *) malloc(sizeof(LinkQueue));
	BiTree e;
	InitQueue(Q);
	EnQueue(Q, bt);
	while (Q->front != Q->rear) {
		DeQueue(Q, &e);
		printf("%d ", e->data);
		EnQueue(Q, e->left);
		EnQueue(Q, e->right);
	}
}

int main() {
	int arr[] = { 0, 1, 2, 3, 4, 5, 6};
	BiTree root;
	CreateTree(&root, arr, sizeof(arr) / sizeof(int), 0);
	printf("PreOrderTraverse: ");
	PreOrderTraverse(root);
	printf("\nBFSOrderTravesre: ");
	BFSTraverse(root);
	return 0;
}

/*
程序运行如下:
PreOrderTraverse: 0 1 3 4 2 5 6
BFSOrderTravesre: 0 1 2 3 4 5 6
 */

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!