`
thecloud
  • 浏览: 881067 次
文章分类
社区版块
存档分类
最新评论

拓扑排序中的栈存储结构

 
阅读更多

近期看数据结构,看到拓扑排序中的栈存储数据结构,上面的栈使用数组进行存储,而非Stack定义,使用的非常妙,分享一下。

拓扑排序的主要思想:(1)选择一个入度为0的顶点并输出;(2)从网中删除此顶点及其所有边;(3)重复执行(1)(2)直到不存在入度为0的顶点;比如下面所示的图(采用邻接表表示):


设置保存每个顶点的入度值的数组d,则d如下所示:


方式一:直接使用d数组作为栈,栈的使用方式如下:

(1)初始化栈,设置链栈指针top为-1;

(2)将入度为0的元素的d[0]进栈,即:的d[0]=top;top=0;此时top指向d[0]元素,表示顶点v0的入度为0,而d[0]的值为-1,表示栈低;

(3)将入度为0的d[1]进栈,即:d[1]=top;top=1;此时top指向d[1]元素,表示顶点v1的入度为0,而d[1]的值为0,表明下一个入度为0的元素为d[0],即对应下一个入度为0的顶点为v0,d[0]的值为-1,所以此栈当前有两个元素d[1]和d[0];

由上面三步步骤初始化数组d为:


删除顶点v1,得到数组d为:


然后依次删除并输出顶点V4,V0,V2,V3,V5(方式一参考《数据结构(c语言描述)》--徐孝凯。。。)

方式二:除了使用数组d外,另外加一个Stack作为栈的存储结构,每次删除一个节点后判断节点的入度是否为零,如果为零则push入Stack中;

Java代码实现如下:

GraphNode节点定义:

package org.fansy.topological.copy;
/**
 * 图的节点定义,含有两个私有变量
 * data:当前节点值;
 * next:下一个节点;
 * @author Administrator
 *
 */
public class GraphNode {
	private int data;
	private GraphNode next;
	public int getData() {
		return data;
	}
	public void setData(int data) {
		this.data = data;
	}
	public GraphNode getNext() {
		return next;
	}
	public void setNext(GraphNode next) {
		this.next = next;
	}	
	public GraphNode(){}
	public GraphNode(int data){
		this.data=data;
	}
	public GraphNode(String data){
		this.data=Integer.parseInt(data);
	}
	public GraphNode(int data,GraphNode next){
		this.data=data;
		this.next=next;
	}
}
图操作:(图创建和图拓扑遍历)

package org.fansy.topological.copy;
import java.util.*;
/**
 * 图操作类
 * 含有创建图方法
 * 
 * @author Administrator
 *
 */
public class GraphOperation {
	/**
	 * 创建一个含有权值的图
	 * @param nodeSize 节点的个数
	 * @return nodes 图存储结构,数组形式
	 */
	public GraphNode[] createGraphTree(int nodeSize){
		GraphNode[] nodesArr=new GraphNode[nodeSize];
		Scanner input=new Scanner(System.in); //  接收键盘输入每个图节点的next域
		for(int i=0;i<nodeSize;i++){
			nodesArr[i]=new GraphNode(i); // 赋值表头节点
			System.out.println("请输入节点 "+i+" 的next 域(逗号分隔)"+
					"比如[next1,next2]或者[null]):");
			String inputStr=input.next();
			if("null".equals(inputStr)){
				continue;
			}
			String[] nodes=inputStr.split(",");
			if(nodes.length<=0){				
				continue;
			}
			GraphNode temp,tempNext;
			tempNext=new GraphNode(nodes[nodes.length-1].split(":")[0]);
			for(int j=nodes.length-2;j>=0;j--){
				temp=new GraphNode(nodes[j].split(":")[0]); 
				temp.setNext(tempNext);
				tempNext=temp;
			}
			nodesArr[i].setNext(tempNext);
		}
		input.close();
		return nodesArr;
	}
	/**
	 * 拓扑排序算法,使用一个top表示栈
	 * @param gl表头数组
	 * @param nodeSize 节点数目 
	 */
	public void topSort(GraphNode[] gl,int nodeSize){
		long start=System.currentTimeMillis();
		int i,j,k,top;
		GraphNode temp;
		// 定义存储图中每个节点入度的一维整型数组
		int[] d=new int[nodeSize];
		for(i=0;i<nodeSize;i++){
			temp=gl[i].getNext();
			while(temp!=null){
				j=temp.getData();
				d[j]++;
				temp=temp.getNext();  //
			}
		}
		//初始化用于链接入度为0的元素的栈的栈顶指针top为-1
		top=-1;
		// 初始化建立栈
		for(i=0;i<nodeSize;i++){
			if(d[i]==0){
				d[i]=top;
				top=i;
			}
		}
		//每循环一次删除一个顶点及其所有出边
		while(top!=-1){
			j=top;  // j的值为一个入度为零的序号
			top=d[top];//删除栈顶元素
			System.out.print(j+",");//输出一个栈顶元素
			temp=gl[j].getNext(); // temp指向顶点gl[j]的下一个节点
			while(temp!=null){
				k=temp.getData();
				d[k]--;
				if(d[k]==0){// 把入度为零的元素进栈
					d[k]=top;
					top=k;
				}
				temp=temp.getNext();
			}
		}
		System.out.println("array time spend:"+(System.currentTimeMillis()-start));
	}	
	/**
	 * 拓扑排序算法,使用一个Stack表示栈
	 * @param gl表头数组
	 * @param nodeSize 节点数目 
	 */
	public void topSort2(GraphNode[] gl,int nodeSize){
		long start=System.currentTimeMillis();
		int i,j,k;
		Stack<Integer> stack=new Stack<Integer>();
		GraphNode temp;
		// 定义存储图中每个节点入度的一维整型数组
		int[] d=new int[nodeSize];
		for(i=0;i<nodeSize;i++){
			temp=gl[i].getNext();
			while(temp!=null){
				j=temp.getData();
				d[j]++;
				temp=temp.getNext();  // 向下转型
			}
		}
		// 初始化建立栈
		for(i=0;i<nodeSize;i++){
			if(d[i]==0){
				stack.push(i);//  把节点压入栈顶
			}
		}
		//每循环一次删除一个顶点及其所有出边
		while(!stack.isEmpty()&&stack.peek()!=null){
			System.out.print(stack.peek()+",");//输出一个栈顶元素
			temp=gl[stack.pop()].getNext(); // ,删除一个栈顶元素
			while(temp!=null){
				k=temp.getData();
				d[k]--;
				if(d[k]==0){// 把入度为零的元素进栈
					stack.push(k);
				}
				temp=temp.getNext();
			}
		}
		System.out.println("stack time spend:"+(System.currentTimeMillis()-start));
	}	
}
测试程序:

package org.fansy.topological.copy;
import java.util.*;
public class TestTopSort {
	/**
	 * 拓扑排序测试程序
	 * @param args
	 */
	public static void main(String[] args) {
		GraphOperation g=new GraphOperation();
		Scanner scan=new Scanner(System.in);
		System.out.println("输入节点的个数:");
		int nodeSize=scan.nextInt();		
		GraphNode[] nodesArr=new GraphNode[nodeSize];
		nodesArr=g.createGraphTree(nodeSize);
		g.topSort(nodesArr, nodeSize);
		System.out.println("\nstack.......");
		g.topSort2(nodesArr, nodeSize);
		scan.close();
	}
}
输出结果如下:


由上面的结果可以看出,不仅方式一的结构存储非常妙,而且遍历耗时减小。


分享,快乐,成长


转载请注明出处:http://blog.csdn.net/fansy1990





分享到:
评论

相关推荐

    数据结构图的遍历及拓扑排序

    /*----------------输出拓扑排序-------------*/ int topsort(linkmap *map) { int k=0,i,j,v,tag[100];//tag用来标记是否已访问到 int queue[100];//用队列存储 int front=0,real=0; edgenode *p; for(i=0;i...

    数据结构拓扑排序课程设计报告

    数据结构课程设计拓扑排序,利用栈实现。实现过程使用邻接表为存储结构,使用数组存储入度为零的顶点,另设一栈暂存所有入度为零的顶顶点。全文包括引言、需求分析、概要设计、详细设计、测试与分析、总结、附录源...

    C#版的数据结构课程设计——有向图的拓扑排序

    数据结构C#的课程设计 拓扑排序 利用邻接表实现数据存储 其中还运用到了栈

    拓扑排序实验报告.doc

    在具体实现拓扑排序的函数中,根据规则,当某个顶点的入度为0(没有前驱顶点)时, 就将此顶点输出,同时将该顶点的所有后继顶点的入度减1,为了避免重复检测入度为0 的顶点,设立一个栈St,以存放入度为0的顶点。...

    数据结构习题答案(全部算法)严蔚敏版

    3.1.2 栈的顺序存储结构(向量) 3.1.3 栈的链表存储结构 3.1.4 栈的应用 3.2 队列 3.2.1 队列的定义及运算 3.2.2 队列的顺序存储结构(向量) 3.2.3 队列的链表存储结构 3.3 栈和队列的算法实现举例 习题...

    数据结构设计大学学习计划

    用拓扑排序和aoe网实现设计大学学习计划,其中包括用顺序栈实现图的储存,用拓扑排序输出学习计划,学戏计划可修改

    数据结构和算法动画演示

    数据结构和算法Flash动画演示 顺序查找 顺序栈(4个存储空间) 顺序栈(8个存储空间) 顺序表的删除运算 顺序表的插入 ...拓扑排序 最短路径 克鲁斯卡尔算法构造最小生成树 B树的删除 B树的生长过程

    计算机专业数据结构设计课件

    拓扑排序 4.关键路径 四、查找 (一)查找的基本概念 (二)顺序查找法 (三)折半查找法 (四)B-树 (五)散列(Hash)表及其查找 (六)查找算法的分析及应用 五、内部排序 (一)排序的基本概念 (二)插入排序...

    精心整理史上最全的数据结构flash演示动画,共5个版本,祝大家考研成功!

    \数据结构flash演示\版本1\7-6-1拓扑排序-有环.swf \数据结构flash演示\版本1\7-7-1关键路径.swf \数据结构flash演示\版本1\9-2-1B-树.swf \数据结构flash演示\版本1\9-2-1顺序查找.swf \数据结构flash演示\版本...

    数据结构总结(自学、期末复习或考研备用).pdf

    、第七章图、图的存储结构:、图的遍历、深度优先遍历(DFS)、广度优先遍历(BFS算法)、最小生成树、普里姆算法、克鲁斯卡尔算法、最短路径、迪杰斯特拉(Dijkstra)算法、弗洛伊德(Floyd)算法、拓扑排序、关键路径、第八...

    数据结构 严蔚敏 代码

    范例1-108 拓扑排序 366 ∷相关函数:TopologicalSort函数 1.7.8 关键路径 374 范例1-109 关键路径 374 ∷相关函数:CriticalPath函数 1.7.9 最短路径 383 范例1-110 最短路径 383 ∷相关函数:ShortestPath_DIJ函数...

    c语言数据结构算法演示(Windows版)

    右下显示拓扑排序过程中入度为零的顶点的栈S,右上显示的栈 T 存放拓扑序列,其入栈顺序和栈 S 的出栈顺序相同,从栈顶到栈底的顶点顺序即为顶点的逆拓扑序列。算法执行结束后将弹出窗口列出全部结果,其中红色字体...

    数据结构—使用C语言(第4版)【朱战立-电子教案】

    拓扑排序 关键路径 【第10章】 排序 图的基本概念 图的存储结构 图的实现 图的遍历 最小生成树 最短路径 拓扑排序 关键路径 【第11章】 查找 查找的基本概念 静态查找表 动态查找表 哈希表

    java算法与数据结构

    (4)拓扑排序 (5)关键路径 (6)单源最短路径 5.散列表(哈希表) (1)散列表的概念 (2)散列表解决散列冲突的方法(开放地址法、链地址法) (3)散列表的插入和删除 6.算法分析与设计基础 (1)分治与递归...

    数据结构02331(苏仕华)

    第六节 拓扑排序 第七章 排序 第一节 基本概念 第二节 插入排序 第三节 交换排序 第四节 选择排序 第五节 归并排序 第六节 分配排序 第七节 内部排序方法的分析比较 第八章 查找 第一节 基本概念 第二节 顺序表的...

    数据结构实践

    图的应用 拓扑排序 TSort 关键路径 CritPath Dijkstra算法 DIJ Floyd算法 FLOYD 10 查找 静态查找 顺序查找、折半查找 SSearch 动态查找 二叉排序树 BSTSearch 散列查找 开放定址 LineHSearch 11 排序 插入...

    考研-数据结构-殷人昆.zip

    3.2 栈和队列的存储结构、算法与应用 56 3.2.1 本章所涉及的结构体定义 56 3.2.2 顺序栈 57 3.2.3 链栈 59 3.2.4 栈的应用 60 3.2.5 顺序队 64 3.2.6 链队 66 3.3 抽象数据类型 69 ▲真题仿造 71 真题仿造答案与讲解...

    数据结构演示软件

    它可适应读者对算法的输入数据和过程执行的控制方式的不同需求, 在计算机的屏幕上显示算法执行过程中数据的逻辑结构或存储结构的变化状况或递归算法执行过程中栈的变化状况。整个系统使用菜单驱动方式, 每个菜单...

    东北大学计算机初试数据结构

    7.4有向无环图、拓扑排序和关键路径。 9 查找 9.1 静态查找表 9.2 动态查找表 9.3 哈希表 10 排序 10.1 插入排序 10.2 快速排序 10.3 选择排序 10.4 归并排序 10.5 基数...

    2003年-数据结构.docx

    ( ) 拓扑排序是一种内部排序的算法。(×) 字符串是一种特殊的线性表,其特殊性体现在数据元素是一个字符。( ) 若线索二叉树有n个结点,则必有n+1条不空的指向树中结点的线索。(×) 稀疏矩阵的压缩存储方法...

Global site tag (gtag.js) - Google Analytics