看数据结构写代码(40) 无向图的深度优先生成树与广度优先生成树

图的深度优先遍历 和 广度 优先 遍历 算法中的 每一次 最外层 循环 都 产生 一个 无向图 的 连通分量,每一个连通分量,都可以产生一个生成树,将这些生成树合在 一起 就是 一个 森林。 用 树的 孩子 兄弟 链表 表示法 来 表示 这个 森林, 就是 这一节 算法的  内容。

深度优先森林 代码 :

//深度优先生成森林
void dfsTree(AMLGraph g,int i,Tree * t,bool isVisited[]){
	isVisited[i] = true;
	bool isFirst = true;
	Tree p,q = NULL;
	for (int next = firstAdj(g,i); next != -1; next = nextAdj(g,i,next)){
		if (isVisited[next] == false){
			p = makeTreeNode(g.adjMuList[next].vexName);
			if (isFirst){
				(*t)->firstChild = p,isFirst = false;
			}
			else{
				q->nextSibling = p;
			}
			q = p;
			dfsTree(g,next,&q,isVisited);
		}

	}
}

void dfsForest(AMLGraph g,Tree * t){
	bool isVisited[MAX_VEX_NUM] = {false};
	*t = NULL;
	Tree p,q;
	for (int i = 0; i < g.vexNum; i++){
		if (isVisited[i] == false){
			p = makeTreeNode(g.adjMuList[i].vexName);//每一次循环都是一颗生成树.
			if (*t == NULL){//第一个是根节点
				*t = p;
			}
			else{//其余生成树 是 第一颗 生成树的 兄弟
				q->nextSibling = p;
			}
			q = p;//保存上一个树
			dfsTree(g,i,&q,isVisited);
		}
	}
}

广度优先生成森林代码:

//广度优先生成森林
void bfsForest(AMLGraph g,Tree * t){
	bool isVisited[MAX_VEX_NUM] = {false};
	Tree treeArray[MAX_VEX_NUM] = {NULL};//记录所有顶点的 树节点坐标.
	//因为要 找到 遍历的 树节点的 父亲 是谁.(这一句p = treeArray[top];)
	Tree p,q,r;
	LinkQueue queue;
	queueInit(&queue);
	for (int i = 0; i < g.vexNum; i++){
		if (isVisited[i] == false){
			p = makeTreeNode(g.adjMuList[i].vexName);
			if (i == 0){//第一颗生成树..
				*t = p;
			}
			else{//其他生成树是 第一颗生成树的 孩子兄弟链表的 兄弟
				//(*t)->nextSibling = p; 这样写 就只有 一个兄弟节点了..
				q->nextSibling = p;
			}
			q = p;
			treeArray[i] = p;
			isVisited[i] = true;
			enqueue(&queue,i);
			while (!queueEmpty(queue)){
				int top;
				dequeue(&queue,&top);
				bool isFirst = true;
				for (int next = firstAdj(g,top);next != -1; next = nextAdj(g,top,next)){
					if (isVisited[next] == false){
						isVisited[next] = true;
						r = makeTreeNode(g.adjMuList[next].vexName);
						treeArray[next] = r;
						if (isFirst){
							p = treeArray[top];
							p->firstChild = r,isFirst = false;
						}
						else{
							p->nextSibling = r;
						}
						p = r;
						enqueue(&queue,next);
					}
				}
			}
		}
	}
	queueDestory(&queue);
}

在写广度 优先生成森林代码中,犯了 两个错误:

1.

//(*t)->nextSibling = p; 这样写 就只有 一个兄弟节点了..

q->nextSibling = p;

2.

没有 写 这句话:

p = treeArray[top];

后来 将所有 顶点的坐标 存到 数组中,好查找 节点的 父亲节点。

详细源代码如下:

工程文件网盘地址:点击打开链接

// AMLGraph.cpp : 定义控制台应用程序的入口点。
//无向图的邻接多重表

#include "stdafx.h"
#include <cstdlib>
#include "queue.h"
#include "BinaryTree.h"

#define MAX_VEX_NUM 20

enum E_VisitIf
{
	unvisited = 0,
	visited = 1,
};
struct ArcNode
{
	E_VisitIf mark;
	int iIndex,jIndex;//顶点i,j在图中的位置
	ArcNode * iNext;//与i顶点点相关的下一个弧
	ArcNode * jNext;//与j顶点点相关的下一个弧
};

struct VNode
{
	char vexName;
	ArcNode * head;//头指针
};

struct AMLGraph
{
	VNode adjMuList[MAX_VEX_NUM];//顶点数组
	int vexNum,arcNum;
};

//获取弧 的 头节点
ArcNode * getHeadNode(){
	ArcNode * pNode = (ArcNode *)malloc(sizeof(ArcNode));
	if (pNode){
		pNode->iIndex = pNode->jIndex = -1;
		pNode->iNext = pNode->jNext = NULL;
		pNode->mark = unvisited;
	}
	return pNode;
}

ArcNode * getArcNode(int iIndex,int jIndex){
	ArcNode * pNode = getHeadNode();
	if (pNode){
		pNode->iIndex = iIndex;
		pNode->jIndex = jIndex;
	}
	return pNode;
}

int vexLocation(AMLGraph g,char vex){
	for (int i = 0; i < g.vexNum; i++){
		if (g.adjMuList[i].vexName == vex){
			return i;
		}
	}
	return -1;
}

void createGrahp(AMLGraph * g){
	printf("输入图的顶点数 和 边(弧)数\n");
	scanf("%d%d%*c",&g->vexNum,&g->arcNum);
    //构造顶点集
    printf("请输入顶点集\n");
    for (int i = 0; i < g->vexNum; i++){
        char name;
		scanf("%c",&name);
		g->adjMuList[i].vexName = name;
		g->adjMuList[i].head = getHeadNode();//建立 头节点,并让头指针指向头节点
    }
    //构造顶点关系
    fflush(stdin);
    printf("请输入顶点的关系\n");
    for (int i = 0; i < g->arcNum; i++){
        char vex1,vex2;
		scanf("%c%c%*c",&vex1,&vex2);
		int location1 = vexLocation(*g,vex1);
		int location2 = vexLocation(*g,vex2);
		ArcNode * pNode = getArcNode(location1,location2);
		pNode->iNext = g->adjMuList[location1].head->iNext;
		g->adjMuList[location1].head->iNext = pNode;
		pNode->jNext = g->adjMuList[location2].head->iNext;
		g->adjMuList[location2].head->iNext = pNode;
    }
}

void destoryGraph(AMLGraph * g){
	for (int i = 0; i < g->vexNum; i++){
		ArcNode * next = g->adjMuList[i].head->iNext;
		while (next != NULL){
			ArcNode * freeNode = next;
			next = next->iIndex == i ? next->iNext : next->jNext;
			if (freeNode->iIndex == i){////只释放 iIndex 等于 i的节点,要不会多次释放
				free(freeNode);
			}
		}
		free(g->adjMuList[i].head);
		g->adjMuList[i].head = NULL;
		g->adjMuList[i].vexName = ' ';
		g->vexNum = g->arcNum = 0;
	}
}

//顶点vex1 和顶点vex2 是否相邻
bool graphIsAdj(AMLGraph g,char vex1,char vex2){
	int location = vexLocation(g,vex1);
	ArcNode * next = g.adjMuList[location].head->iNext;
	while (next != NULL){
		if (g.adjMuList[next->iIndex].vexName == vex2 || g.adjMuList[next->jIndex].vexName == vex2){
			return true;
		}
		next = next->iIndex == location ? next->iNext : next->jNext;
	}
	return false;
}

int graphDegree(AMLGraph g,char vex){
	int degree = 0;
	int location = vexLocation(g,vex);
	ArcNode * next = g.adjMuList[location].head->iNext;//计算所有出度
	while (next != NULL){
		degree++;
		next = next->iIndex == location ? next->iNext : next->jNext;
	}
	return degree;
}

//插入边(弧)
void insertArc(AMLGraph * g,char vex1,char vex2){
	int location1 = vexLocation(*g,vex1);
	int location2 = vexLocation(*g,vex2);
	ArcNode * node = getArcNode(location1,location2);
	node->iNext = g->adjMuList[location1].head->iNext;
	g->adjMuList[location1].head->iNext = node;
	node->jNext = g->adjMuList[location2].head->iNext;
	g->adjMuList[location2].head->iNext = node;
	g->arcNum ++;
}
//删除边(弧)
void deleteArc(AMLGraph * g,char vex1,char vex2){
	g->arcNum--;
	int location1 = vexLocation(*g,vex1);
	int location2 = vexLocation(*g,vex2);
	ArcNode * next = g->adjMuList[location1].head->iNext;
	ArcNode * pre = g->adjMuList[location1].head;
	while (next != NULL){
		if (next->iIndex == location2){
			if (pre == g->adjMuList[location1].head || pre->iIndex == location1){//删除的是第一个节点.或者 前驱的index = location1
				pre->iNext = next->jNext;
			}
			else{
				pre->jNext = next->jNext;
			}
			break;
		}
		else if(next->jIndex == location2){
			if (pre == g->adjMuList[location1].head || pre->iIndex == location1){//删除的是第一个节点.或者 前驱的index = location1
				pre->iNext = next->iNext;
			}
			else{
				pre->jNext = next->iNext;
			}
			break;
		}
		pre = next;
		next = next->iIndex == location1 ? next->iNext : next->jNext;
	}
	next = g->adjMuList[location2].head->iNext;
	pre = g->adjMuList[location2].head;
	while (next != NULL){
		if (next->iIndex == location1){
			if (pre == g->adjMuList[location2].head || pre->iIndex == location2){//删除的是第一个节点.或者 前驱的index = location1
				pre->iNext = next->jNext;
			}
			else{
				pre->jNext = next->jNext;
			}
			free(next);
			break;
		}
		else if(next->jIndex == location1){
			if (pre == g->adjMuList[location2].head || pre->iIndex == location2){//删除的是第一个节点.或者 前驱的index = location1
				pre->iNext = next->iNext;
			}
			else{
				pre->jNext = next->iNext;
			}
			free(next);
			break;
		}
		pre = next;
		next = next->iIndex == location2 ? next->iNext : next->jNext;
	}
}
//插入顶点
void insertVex(AMLGraph * g, char vex){
	if (g->vexNum < MAX_VEX_NUM){
		g->adjMuList[g->vexNum].vexName = vex;
		g->adjMuList[g->vexNum].head = getHeadNode();
		g->vexNum++;
	}
}
//删除顶点
void deleteVex(AMLGraph * g,char vex){
	int location = vexLocation(*g,vex);
	//删除顶点 同样需要 遍历整个 图 查找 与 vex 相关的弧节点
	for (int i = 0; i < g->vexNum; i++){
		ArcNode * next = g->adjMuList[i].head->iNext;
		while (next != NULL){
			if (next->iIndex == location || next->jIndex == location){
				ArcNode * delNode = next;
				next = next->iIndex == location ? next->iNext : next->jNext;
				char delData1 = g->adjMuList[delNode->iIndex].vexName;
				char delData2 = g->adjMuList[delNode->jIndex].vexName;
				deleteArc(g,delData1,delData2);
			}
			else{
				next = next->iIndex == location ? next->iNext : next->jNext;
			}
		}
	}
	//更改因删除顶点 而导致的元素位置变化..
	for (int i = 0; i < g->vexNum; i++){
		ArcNode * next = g->adjMuList[i].head->iNext;
		while (next != NULL){
			if (next->iIndex == i){
				if(next->iIndex > location){
				next->iIndex --;
				}
				if(next->jIndex > location){
					next->jIndex --;
				}
			}
			next = next->iIndex == location ? next->iNext : next->jNext;
		}
	}
	free(g->adjMuList[location].head);//释放头节点
	//vex下面的 顶点上移
	for (int i = location + 1; i < g->vexNum; i++){
		g->adjMuList[i-1] = g->adjMuList[i];
	}
	g->vexNum --;
}

void printGrahp(AMLGraph g){
	for (int i = 0; i < g.vexNum; i++){
		printf("%c的 邻接点有:",g.adjMuList[i].vexName);
		ArcNode * next = g.adjMuList[i].head->iNext;//删除所有弧尾
		while (next != NULL){
			int index = next->iIndex == i ? next->jIndex : next->iIndex;
			printf("%c",g.adjMuList[index].vexName);
			next = next->iIndex == i ? next->iNext : next->jNext;
		}
		printf("\n");
	}
}

int firstAdj(AMLGraph g,int location){
	ArcNode * next = g.adjMuList[location].head->iNext;
	if (next != NULL)
	{
		int index = next->iIndex == location ? next->jIndex : next->iIndex;
		return index;
	}
	return -1;
}

int nextAdj(AMLGraph g,int location1 ,int location2){
	ArcNode * next = g.adjMuList[location1].head->iNext;
	while (next != NULL){
		if (next->iIndex == location2 || next->jIndex == location2){
			next = next->iIndex == location1 ? next->iNext : next->jNext;
			break;
		}
		next = next->iIndex == location1 ? next->iNext : next->jNext;
	}
	if (next != NULL){
		int index = next->iIndex == location1 ? next->jIndex : next->iIndex;
		return index;
	}
	return -1;
}
/*
void dfs(AMLGraph g,int i,bool * isVisitedArray){
	printf("%c",g.adjMuList[i].vexName);
	isVisitedArray[i] = true;
	for (int next = firstAdj(g,i); next != -1 ; next = nextAdj(g,i,next)){
		if (isVisitedArray[next] == false){
			dfs(g,next,isVisitedArray);
		}
	}
}
//深度优先搜索遍历
void dfsTraver(AMLGraph g){
	bool isVisited[MAX_VEX_NUM] = {false};
	printf("----------深度优先遍历------------------\n");
	for (int i = 0; i < g.vexNum; i++){
		if (isVisited[i] == false){
			dfs(g,i,isVisited);
		}
	}
	printf("\n");
}
//广度优先搜索遍历
void bfsTraverse(AMLGraph g){
	bool isVisited[MAX_VEX_NUM] = {false};
	printf("----------广度优先遍历------------------\n");
	LinkQueue queue;
	queueInit(&queue);
	for (int i = 0; i < g.vexNum; i++){
		if (isVisited[i] == false){
			printf("%c",g.adjMuList[i].vexName);
			isVisited[i] = true;
			enqueue(&queue,i);
			while (!queueEmpty(queue)){
				int top;
				dequeue(&queue,&top);
				for (int next = firstAdj(g,top);next != -1 ; next = nextAdj(g,top,next)){
					if (isVisited[next] == false){
						printf("%c",g.adjMuList[next].vexName);
						isVisited[next] = true;
						enqueue(&queue,next);
					}
				}
			}
		}
	}
	queueDestory(&queue);
}

void dfsTree(AMLGraph g,int v,Tree * t,bool * isVisited){
	isVisited[v] = true;
	bool first = true;
	Tree p,q= NULL;
	for (int next = firstAdj(g,v);next != -1 ;next = nextAdj(g,v,next)){
		if (isVisited[next] == false){
			p = makeTreeNode(g.adjMuList[next].vexName);
			if (first){
				(*t)->firstChild = p;first = false;
			}
			else{
				q->nextSibling = p;
			}
			q = p;
			dfsTree(g,next,&q,isVisited);
		}
	}
}

//深度优先遍历生成森林
void dfsForest(AMLGraph g,Tree * tree){
	bool isVisited[MAX_VEX_NUM] = {false};
	*tree = NULL;
	Tree p,q;
	for (int i = 0; i <g.vexNum ; i++){
		if (isVisited[i] == false){
			p = makeTreeNode(g.adjMuList[i].vexName);
			if (!*tree){
				*tree = p;//根节点.
			}
			else{
				q->nextSibling = p;
			}
		}
		q = p;//q指向当前生成树的根..
		dfsTree(g,i,&p,isVisited);
	}
}
*/
void dfs(AMLGraph g,int i,bool isVisited[]){
	printf("%c",g.adjMuList[i].vexName);
	isVisited[i] = true;
	for (int next = firstAdj(g,i); next != -1; next = nextAdj(g,i,next)){
		if (isVisited[next] == false){
			dfs(g,next,isVisited);
		}
	}
}

//深搜
void dfsTraverse(AMLGraph g){
	bool isVisited[MAX_VEX_NUM] = {false};
	printf("---------深度优先搜索遍历---------\n");
	for (int i = 0; i < g.vexNum; i++){
		if (isVisited[i] == false){//未访问过
			dfs(g,i,isVisited);
		}
	}
	printf("\n");
}

//广搜
void bfsTraverse(AMLGraph g){
	bool isVisited[MAX_VEX_NUM] = {false};
	printf("---------广度优先搜索遍历---------\n");
	LinkQueue queue;
	queueInit(&queue);
	for (int i = 0; i < g.vexNum; i++){
		if (isVisited[i] == false){
			enqueue(&queue,i);
			printf("%c",g.adjMuList[i].vexName);
			isVisited[i] = true;
			while (!queueEmpty(queue)){
				int top;
				dequeue(&queue,&top);
				for (int next = firstAdj(g,top); next != -1; next = nextAdj(g,top,next)){
					if (isVisited[next] == false){
						printf("%c",g.adjMuList[next].vexName);
						isVisited[next] = true;
						enqueue(&queue,next);
					}
				}
			}
		}
	}
	queueDestory(&queue);
	printf("\n");
}

//深度优先生成森林
void dfsTree(AMLGraph g,int i,Tree * t,bool isVisited[]){
	isVisited[i] = true;
	bool isFirst = true;
	Tree p,q = NULL;
	for (int next = firstAdj(g,i); next != -1; next = nextAdj(g,i,next)){
		if (isVisited[next] == false){
			p = makeTreeNode(g.adjMuList[next].vexName);
			if (isFirst){
				(*t)->firstChild = p,isFirst = false;
			}
			else{
				q->nextSibling = p;
			}
			q = p;
			dfsTree(g,next,&q,isVisited);
		}

	}
}

void dfsForest(AMLGraph g,Tree * t){
	bool isVisited[MAX_VEX_NUM] = {false};
	*t = NULL;
	Tree p,q;
	for (int i = 0; i < g.vexNum; i++){
		if (isVisited[i] == false){
			p = makeTreeNode(g.adjMuList[i].vexName);//每一次循环都是一颗生成树.
			if (*t == NULL){//第一个是根节点
				*t = p;
			}
			else{//其余生成树 是 第一颗 生成树的 兄弟
				q->nextSibling = p;
			}
			q = p;//保存上一个树
			dfsTree(g,i,&q,isVisited);
		}
	}
}

//广度优先生成森林
void bfsForest(AMLGraph g,Tree * t){
	bool isVisited[MAX_VEX_NUM] = {false};
	Tree treeArray[MAX_VEX_NUM] = {NULL};//记录所有顶点的 树节点坐标.
	//因为要 找到 遍历的 树节点的 父亲 是谁.(这一句p = treeArray[top];)
	Tree p,q,r;
	LinkQueue queue;
	queueInit(&queue);
	for (int i = 0; i < g.vexNum; i++){
		if (isVisited[i] == false){
			p = makeTreeNode(g.adjMuList[i].vexName);
			if (i == 0){//第一颗生成树..
				*t = p;
			}
			else{//其他生成树是 第一颗生成树的 孩子兄弟链表的 兄弟
				//(*t)->nextSibling = p; 这样写 就只有 一个兄弟节点了..
				q->nextSibling = p;
			}
			q = p;
			treeArray[i] = p;
			isVisited[i] = true;
			enqueue(&queue,i);
			while (!queueEmpty(queue)){
				int top;
				dequeue(&queue,&top);
				bool isFirst = true;
				for (int next = firstAdj(g,top);next != -1; next = nextAdj(g,top,next)){
					if (isVisited[next] == false){
						isVisited[next] = true;
						r = makeTreeNode(g.adjMuList[next].vexName);
						treeArray[next] = r;
						if (isFirst){
							p = treeArray[top];
							p->firstChild = r,isFirst = false;
						}
						else{
							p->nextSibling = r;
						}
						p = r;
						enqueue(&queue,next);
					}
				}
			}
		}
	}
	queueDestory(&queue);
}

//邻接多重表
int _tmain(int argc, _TCHAR* argv[])
{
	AMLGraph g;
	createGrahp(&g);
	printGrahp(g);
	dfsTraverse(g);
	bfsTraverse(g);
	Tree tree;
	dfsForest(g,&tree);
	printf("\n----------深度优先遍历生成森林(先序遍历)------------------\n");
	preOrderTraverse(tree);
	treeDestory(&tree);
	bfsForest(g,&tree);
	printf("\n----------广度优先遍历生成森林(先序遍历)------------------\n");
	preOrderTraverse(tree);
	treeDestory(&tree);
	destoryGraph(&g);
	return 0;
}

运行截图:

时间: 2024-11-15 13:49:39

看数据结构写代码(40) 无向图的深度优先生成树与广度优先生成树的相关文章

看数据结构写代码(41) 强连通分量

首先介绍概念问题,在有向图中,若 顶点v1 到 v2 存成路径,并且 v2 到 v1 存成 路径,则称 顶点 v1 和 v2 是强连通的.若 有向图 任意两个节点 都是 强连通的,则 称为强连通图.非强连通图的 极大强连通子图,为 强连通分量. 特别说明,连通的概念 属于 无向图,强连通 属于 有向图.例如:无向图:连通图,连通分量,生成树: 有向图:强连通图,强连通分量. 数据结构书上 简单的 说了 一个 求 强连通 分量的 一个 办法,详细如下: 其实 自己 不太明白 这个算法的原理. 好在

看数据结构写代码(32) 赫夫曼树编码以及译码

杂谈:最近有点慵懒,不好不好.好几天都没写代码,原本准备上星期完结 树 这一章节的.现在 又耽误了.哎.要抓紧时间啊. 下面直接上代码: 可以到我的网盘下载源代码,或者 直接拷贝下面的源代码 运行 网盘地址:点击打开链接 // HuffmanTree.cpp : 定义控制台应用程序的入口点. //哈弗曼编码,译码 #include "stdafx.h" #include <stdlib.h> #include <cstring> enum E_State { E

看数据结构写代码(44) 判断无向图是否有环路

在 看 严蔚敏的 数据结构 一书 7.5小节时,书上 说" 判断有向图是否存在环要不无向图复杂.对于无向图来说,深度优先遍历过程中遇到回边(即指向已访问过的顶点的边),则必定存在环路". 看的不明白,所以 网上 百度了一下. 有了思路:故写下算法 和思路,以便以后 温故. 思路: 1.一个n个顶点,e条边的 无向图,若 e>= n,必有环路. 2.若 e < n ,需要 深度 遍历,并把 父节点传入 参数中,如果 遇到 一个 节点 被访问过 并且 不是 父节点,那么 就有环

看数据结构写代码(43) 关节点

首先 说明一下 概念问题: 关节点 :如果删除无向 图中的一个顶点,以及与顶点相关的边,把 图的 一个连通 分量 变成 两个 以上的 连通 分量.这样的顶点叫做关节点. 没有 关节点的 无向图,叫做 重连通图.重连通图中 任意 两个顶点 至少 存在 两条以上的 通路. 如果 删除 连通图上的 k个 节点,才能 破坏 他的连通性,那么 这个连通图的 连通度 为k. 下面的算法 是 求 连通图的 关节点,并没有 考虑 求图的 关节点,不过 要 改成 图的 关节点 也不难,只要 加 一个 for i

看数据结构写代码(67) 置换 _ 选择排序(完结篇)

杂谈: 严蔚敏版<数据结构(C语言版)> 一书 终于看完了.这是 一个完结,也是 一个新的开端.<算法导论> 已到手. 置换选择排序的思想 是 将 归并段 尽量 变的 更大,而不是根据 内存 大小 限制在 固定的 大小. 这样 可以 利用赫夫曼树 来 进行 最优归并树,从而 使 外存 读写次数 最少. 下面给出 具体 代码:欢迎指出代码不足. // Replace_Selcetion.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h&q

看数据结构写代码(35) 图的邻接矩阵表示法

杂谈:最近清明小长假,好好的放松了一下.节前 和 节后 都有点 松懈.不好,不好.贵在坚持.加油. 图的邻接矩阵表示法是用 两个数组 来表示 图的数据结构.一个是顶点数组,另一个是邻接矩阵数组.邻接矩阵 里存放着 顶点的关系. 用邻接矩阵表示图,在 看 顶点之间 是否有边,或者 求顶点的度等操作时比较简单.但空间浪费巨大,在插入,删除 顶点 和边 操作时 需要 移动大量数据,造成不便.所以在插入删除比较多,节点数比较多的时候 不宜 使用这种结构. 下面上代码: 源代码网盘地址:点击打开链接 //

看数据结构写代码(39) 图的遍历(深搜和广搜)

图的遍历算法 有两种 :深度优先搜索遍历 和 广度 优先搜索遍历.深度优先搜索遍历类似与 树的 先序遍历.广度优先搜索遍历类似与树的层序遍历.只不过 图 可以有 不连通的 节点,所以 得 遍历 整个顶点数组. 深搜遍历 总是 先访问当前节点的邻接点,而 广搜算法 是 先访问顶点的邻接点 要 先于 后访问顶点的邻接点 被 访问. 具体遍历顺序如下: 以下代码 以 图的 邻接多重表 为 基本结构进行 遍历. 首先更改 上节 的 查找 邻接点 和 下一个邻接点的 返回值,以及 邻接点的 代码 有误,少

看数据结构写代码(66) 败者树

计算机的 内存 是 有限的,无法 存入 庞大的数据.当 遇到 大数据需要排序时,我们 需要 将 这些 数据 分段 从 硬盘里 读到 内存中,排好序,再 写入到 硬盘中,这些段 叫做 归并段.最后将 这些 分段 合并 成 一个 最终  完整 有序的 数据. 这里 操作的 时间 =  内部 排序 时间 +  外存读写时间 + 内部归并所需时间. 其中 外存 读写时间 最耗时,外存读写时间 = 读写次数 * 读写数据的时间 ,读写 数据的时间 因 设备 性能 而 影响,我们 无法控制,我们 只能 控制

看数据结构写代码(42)最小生成树

首先给出 一些 概念问题: 1.生成树: 一个n个顶点的 连通图 的 极小连通子图. 它含有n个顶点,但只有 n-1条边,不存在回路. 2.最小生成树:一个带权的 无向连通图,求出 各边权值相加  最小的 生成树,叫做最小生成树. 所以 求最小生成树  首先 要满足: 1. 首先 是 无向图 2. 必须是 连通图(任意两个顶点可达)3.带权 简单的说 就是 必须是 连通网. 求 最小生成树,严蔚敏的 数据结构 给出了 两种 方法:普里姆算法和 克鲁斯卡尔算法. 普里姆算法: 克鲁斯卡尔算法: 克