`
wujianjun12315
  • 浏览: 112971 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java实现数据结构图

阅读更多
考虑一个任务安排的例子,比如有很多任务T1,T2,....
这些任务又是相互关联的,比如Tj完成前必须要求Ti已完成,这样T1,T2....序列关于这样的先决条件构成一个图,其中如果Ti必须要先于Tj完成,那么<Ti,Tj>就是该图中的一条路径,路径长度为1的就是一条边。
拓扑排序就是把这些任务按照完成的先后顺序排列出来。显然,这样的顺序可能不是唯一的,比如Tk,Tl如果没有在一条路径上,那么他们之间的顺序是任意的。
拓扑排序至少有两种解法

1)首先找出入度(连接到改点的边的数目)为零的顶点放入队列,然后依次遍历这些顶点,每次访问到其中的一个顶点时,把该定点关联到的其它顶点的边移去,也就是使得关联顶点的入度减1.如果减1后该定点入度也变为0了,那么把该定点加入队列下次从他开始处理,直到没有入度为0的定点了。
这里要注意,如果给定的图有回路那么,可能不会处理完所有顶点就退出了。

实现如下:

private final void calculateInDegrees(int[] inDegrees)
    {
        Arrays.fill(inDegrees, 0);
        for(int v=0;v<numVertexes;v++)
        {
            for(Edge e=firstEdge(v);isEdge(e);e=nextEdge(e))
            {
                inDegrees[toVertex(e)]++;
            }
        }
    }
    /**
     *
     * @param sortedVertexes
     */
    public void topologySort(int[] sortedVertexes)
    {
        //first calculate the inDegrees
        int[] inDegrees=new int[numVertexes];
        calculateInDegrees(inDegrees);
       
        Arrays.fill(visitTags, false);
       
        _IntQueue queue=new _IntQueue();
       
        for(int v=0;v<numVertexes-1;v++)
        {
            if(inDegrees[v]==0)queue.add(v);
        }
       
       
        int index=0;
        while(!queue.isEmpty())
        {
           
            int from=queue.remove();
            System.out.println("visit:"+from);
            sortedVertexes[index++]=from;
            for(Edge e=firstEdge(from);isEdge(e);e=nextEdge(e))
            {
               
                if(--inDegrees[toVertex(e)]==0)
                {
                    queue.add(toVertex(e));
                }
            }
        }
        if(index<numVertexes)
        {
            throw new IllegalArgumentException("There is a loop");
        }
       
    }
这里一开始计算了各个顶点的入度,计算的时候,每条边需要访问一次。
如果是相邻矩阵的存储方式,计算入度只需要计算每列的非零个数。
一般也可以静态的给出。

2)借助于图的深度优先周游,每次在回退到改顶点的时候把该顶点送入结果数组。
这样得到的数组恰好就是拓扑排序的逆序,因为最底层的节点是最先回退到的。
实现:
/**
     *
     * @param sortedVertexes
     */
    public void topologySort_byDFS(int[] sortedVertexes)
    {
        Arrays.fill(visitTags, false);
        int num=0;
        for(int i=0;i<numVertexes;i++)
        {
            if(!visitTags[i])num=do_topsort(i,sortedVertexes,num);
        }
       
    }



    private final int do_topsort(int v, int[] sortedVertexes, int num) {
        visitTags[v]=true;
       
        for(Edge e=firstEdge(v);isEdge(e);e=nextEdge(e))
        {
            if(!visitTags[toVertex(e)])num=do_topsort(toVertex(e),sortedVertexes,num);
        }
        num++;
        sortedVertexes[numVertexes-num]=v;
   
       
        return num;
    }



    /**
     * Given graph :
     *
     * C1 → C3 ← C2
     * ↓    ↓    ↓
     * C8    C4   C5
     * ↓    ↓    ↓
     * C9 → C7 ← C6
     */
    public static void testTopologySort()
    {
        DefaultGraph g=new DefaultGraph(9);
        g.setEdge(0, 1, 0);
        g.setEdge(2, 1, 0);
        g.setEdge(0, 3, 0);
        g.setEdge(1, 4, 0);
        g.setEdge(2, 5, 0);
        g.setEdge(3, 6, 0);
        g.setEdge(4, 7, 0);
        g.setEdge(5, 8, 0);
        g.setEdge(6, 7, 0);
        g.setEdge(8, 7, 0);
       
       
        g.assignLabels(new String[]{"C1","C3","C2","C8","C4","C5","C9","C7","C6"});
       
        int[] sorted=new int[g.vertexesNum()];
//        g.topologySort(sorted);
        g.topologySort_byDFS(sorted);
        System.out.println("Topology Sort Result==============:");
        for(int i=0;i<sorted.length;i++)System.out.print(g.getVertexLabel(sorted[i])+",");
        System.out.println();
    }

五 最短路径问题

最短路径问题分两类,一类是单源最短路径问题,就是从指定顶点出发到其他各点的最短距离,还有一类是
每两个顶点之间的最短距离,当然第二类也可以通过对每个顶点做一次单源最短路径求解,但是还有一种更优雅的方法(Floyd算法),这种方法一般使用相邻矩阵的实现方式,对每个顶点看它是不是能作为其它没两对顶点间的直接中间节点,如果能,那么再看是不是通过它的两两顶点的距离是不是减小了,若果是就更新这两对顶点间的距离,这样通过每次“贪婪的”找出局部最优解来得到全局最优解,可以算是一个动态规划的解法。
首先我们需要一个辅助类来保存距离,以及回溯路径的类:
public static class Dist implements Comparable<Dist>
    {
        public int preV;
        public int curV;
        public int distance;
       
        public Dist(int v)
        {
            this.curV=v;
            this.preV=-1;
            this.distance=Integer.MAX_VALUE;
        }
       
   
        @Override
        public int compareTo(Dist other) {
            return distance-other.distance;
        }
       
    }
下面给出第二类最短路径的解法(Floyd算法)Java实现:
@Override
    public void floyd(Dist[][] dists) {
        for(int i=0;i<numVertexes;i++)
        {
            dists[i]=new Dist[numVertexes];
            for(int j=0;j<numVertexes;j++)
            {
                dists[i][j]=new Dist(-1);//
                dists[i][j].preV=-1;
                if(i==j)
                    dists[i][j].distance=0;
               
                else
                   dists[i][j].distance=Integer.MAX_VALUE;
               
            }
        }
       
        for(int v=0;v<numVertexes;v++)
        {
            for(Edge e=firstEdge(v);isEdge(e);e=nextEdge(e))
            {
                int to=toVertex(e);
                dists[v][to].distance=e.getWeight();
                dists[v][to].preV=v;
            }
        }
       
        for(int v=0;v<numVertexes;v++)
        {
            for(int i=0;i<numVertexes;i++)
                for(int j=0;j<numVertexes;j++)
                {
                   
                    if((dists[i][v].distance!=Integer.MAX_VALUE)&&(dists[v][j].distance!=Integer.MAX_VALUE)&&(dists[i][v].distance+dists[v][j].distance<dists[i][j].distance))
                    {
                        dists[i][j].distance=dists[i][v].distance+dists[v][j].distance;
                        dists[i][j].preV=v;
                    }
                }
        }
       
    }

/**
     * A Graph example
     * we mark the vertexes  with 0,1,2,.14 from left to right , up to down
     * S-8-B-4-A-2-C-7-D
     * |    |     |     |     |
     * 3    3     1     2     5
     * |    |     |     |     |
     * E-2-F-6-G-7-H-2-I
     * |    |     |     |     |
     * 6    1     1     1     2
     * |    |     |     |     |
     * J-5-K-1-L-3-M-3-T
     *
     */
    public static void testFloyd() {
        DefaultGraph g=new DefaultGraph(15);
        g.setEdge(0, 1,;
        g.setEdge(1, 0,;//its a undirected graph
        g.setEdge(1, 2, 4);
        g.setEdge(2, 1, 4);
        g.setEdge(2, 3, 2);
        g.setEdge(3, 2, 2);
        g.setEdge(3, 4, 7);
        g.setEdge(4, 3, 7);
       
        g.setEdge(0, 5, 3);
        g.setEdge(5, 0, 3);
        g.setEdge(1, 6, 3);
        g.setEdge(6, 1, 3);
        g.setEdge(2, 7, 1);
        g.setEdge(7, 2, 1);
        g.setEdge(3, 8, 2);
        g.setEdge(8, 3, 2);
        g.setEdge(4, 9, 5);
        g.setEdge(9, 4, 5);
       
       
        g.setEdge(5, 6, 2);
        g.setEdge(6, 5, 2);
        g.setEdge(6, 7, 6);
        g.setEdge(7, 6, 6);
        g.setEdge(7, 8, 7);
        g.setEdge(8, 7, 7);
        g.setEdge(8, 9, 2);
        g.setEdge(9, 8, 2);
       
       
        g.setEdge(10, 5, 6);
        g.setEdge(5, 10, 6);
        g.setEdge(11, 6, 1);
        g.setEdge(6, 11, 1);
        g.setEdge(12, 7, 1);
        g.setEdge(7, 12, 1);
        g.setEdge(13, 8, 1);
        g.setEdge(8, 13, 1);
        g.setEdge(14, 9, 2);
        g.setEdge(9, 14, 2);
       
        g.setEdge(10, 11, 5);
        g.setEdge(11, 10, 5);
        g.setEdge(11, 12, 1);
        g.setEdge(12, 11, 1);
        g.setEdge(12, 13, 3);
        g.setEdge(13, 12, 3);
        g.setEdge(13, 14, 3);
        g.setEdge(14, 13, 3);
       
        g.assignLabels(new String[]{"S","B","A","C","D","E","F","G","H","I","J","K","L","M","T"});
       
        Dist[][] dists=new Dist[15][15];
        g.floyd(dists);
       
        System.out.println("Shortes path from S-T ("+dists[0][14].distance+")is:");
        Stack<String> stack=new Stack<String>();
        int i=0;
        int j=14;
        while(j!=i)
        {
           
            stack.push(g.getVertexLabel(j));
            j=dists[i][j].preV;
           
        }
        stack.push(g.getVertexLabel(i));
        while(!stack.isEmpty())
        {
            System.out.print(stack.pop());
            if(!stack.isEmpty())System.out.print("->");
        }
        System.out.println();
       

    }



单源最短路径问题的解法有Dijstra提出,所以也叫Dijstra算法。
它把顶点分为两个集合一个是已求出最短距离的顶点集合V1,另一类是暂未求出的顶点集合V2,而可以证明下一个将求出来(V2中到出发点最短距离值最小)的顶点的最短路径上的顶点除了该顶点不在V1中外其余顶点都在V1中。

如此,先把出发点放入V1中(出发点的最短距离当然也就是0),然后每次选择V2中到出发点距离最短的点加入V1,并把标记改点的最短距离.直到V2中没有顶点为止,详细的形式化证明见:
Dijstra算法证明

这里的实现我们使用最小值堆来每次从V2中挑出最短距离。

先给出最小值堆的实现:
package algorithms;

import java.lang.reflect.Array;

public class MinHeap<E extends Comparable<E>>
{
       
        private E[] values;
        int len;
       
        public MinHeap(Class<E> clazz,int num)
        {
           
            this.values=(E[])Array.newInstance(clazz,num);
            len=0;
        }
           
       
        public final E removeMin()
        {
            E ret=values[0];
            values[0]=values[--len];
            shift_down(0);
            return ret;
        }
   
       
        //insert to tail
        public final void insert(E val)
        {
            values[len++]=val;
            shift_up(len-1);
           
        }
       
        public final void rebuild()
        {
            int pos=(len-1)/2;
            for(int i=pos;i>=0;i--)
            {
                shift_down(i);
            }
        }
       
        public final boolean isEmpty()
        {
            return len==0;
        }
       
        /**
         * When insert element we  need shiftUp
         * @param array
         * @param pos
         */
        private final void shift_up(int pos)
        {
   
            E tmp=values[pos];
            int index=(pos-1)/2;
            while(index>=0)
            {
                if(tmp.compareTo(values[index])<0)
                {
                    values[pos]=values[index];
                    pos=index;
                    if(pos==0)break;
                    index=(pos-1)/2;
                }
                else break;
            }
            values[pos]=tmp;
        }
        private final void shift_down(int pos)
        {
           
            E tmp=values[pos];
            int index=pos*2+1;//use left child
            while(index<len)//until no child
            {
                if(index+1<len&&values[index+1].compareTo(values[index])<0)//right child is smaller
                {
                    index+=1;//switch to right child
                }
                if(tmp.compareTo(values[index])>0)
                {
                    values[pos]=values[index];
                    pos=index;
                    index=pos*2+1;
                   
                }
                else
                {
                    break;
                }
               
            }
            values[pos]=tmp;
           
                   
        }
    }
下面是基于最小值堆的最短路劲算法以及一个测试方法:


    public void dijstra(int fromV,Dist[] dists)
    {
        MinHeap<Dist> heap=new MinHeap<Dist>(Dist.class,numVertexes*2);
       
        for(int v=0;v<numVertexes;v++)
        {
            dists[v]=new Dist(v);
        }
       
        Arrays.fill(visitTags, false);
        dists[fromV].distance=0;
        dists[fromV].preV=-1;
        heap.insert(dists[fromV]);
        int num=0;
       
        while(num<numVertexes)
        {
            Dist dist=heap.removeMin();
            if(visitTags[dist.curV])
            {
                continue;
            }
            visitTags[dist.curV]=true;
            num++;
            for(Edge e=firstEdge(dist.curV);isEdge(e);e=nextEdge(e))
            {
                if(!visitTags[toVertex(e)]&&e.getWeight()+dist.distance<dists[toVertex(e)].distance)
                {
                   
                    dists[toVertex(e)].distance=e.getWeight()+dist.distance;
                    dists[toVertex(e)].preV=dist.curV;
                    heap.insert(dists[toVertex(e)]);
                   
                }
            }
           
        }
       
       
    }


   
    /**
     * A Graph example
     * we mark the vertexes  with 0,1,2,.14 from left to right , up to down
     * S-8-B-4-A-2-C-7-D
     * |   |   |   |   |
     * 3   3   1   2   5
     * |   |   |   |   |
     * E-2-F-6-G-7-H-2-I
     * |   |   |   |   |
     * 6   1   1   1   2
     * |   |   |   |   |
     * J-5-K-1-L-3-M-3-T
     *
     */
    public static void testDijstra()
    {
        DefaultGraph g=new DefaultGraph(15);
        g.setEdge(0, 1,;
        g.setEdge(1, 0,;//its a undirected graph
        g.setEdge(1, 2, 4);
        g.setEdge(2, 1, 4);
        g.setEdge(2, 3, 2);
        g.setEdge(3, 2, 2);
        g.setEdge(3, 4, 7);
        g.setEdge(4, 3, 7);
       
        g.setEdge(0, 5, 3);
        g.setEdge(5, 0, 3);
        g.setEdge(1, 6, 3);
        g.setEdge(6, 1, 3);
        g.setEdge(2, 7, 1);
        g.setEdge(7, 2, 1);
        g.setEdge(3, 8, 2);
        g.setEdge(8, 3, 2);
        g.setEdge(4, 9, 5);
        g.setEdge(9, 4, 5);
       
       
        g.setEdge(5, 6, 2);
        g.setEdge(6, 5, 2);
        g.setEdge(6, 7, 6);
        g.setEdge(7, 6, 6);
        g.setEdge(7, 8, 7);
        g.setEdge(8, 7, 7);
        g.setEdge(8, 9, 2);
        g.setEdge(9, 8, 2);
       
       
        g.setEdge(10, 5, 6);
        g.setEdge(5, 10, 6);
        g.setEdge(11, 6, 1);
        g.setEdge(6, 11, 1);
        g.setEdge(12, 7, 1);
        g.setEdge(7, 12, 1);
        g.setEdge(13, 8, 1);
        g.setEdge(8, 13, 1);
        g.setEdge(14, 9, 2);
        g.setEdge(9, 14, 2);
       
        g.setEdge(10, 11, 5);
        g.setEdge(11, 10, 5);
        g.setEdge(11, 12, 1);
        g.setEdge(12, 11, 1);
        g.setEdge(12, 13, 3);
        g.setEdge(13, 12, 3);
        g.setEdge(13, 14, 3);
        g.setEdge(14, 13, 3);
       
        g.assignLabels(new String[]{"S","B","A","C","D","E","F","G","H","I","J","K","L","M","T"});
       
        Dist[] dists=new Dist[15];
        g.dijstra(0, dists);
       
        System.out.println("Shortes path from S-T ("+dists[14].distance+")is:");
        Stack<String> stack=new Stack<String>();
        for(int v=dists[14].curV;v!=-1;v=dists[v].preV)
        {
            stack.push(g.getVertexLabel(v));
       
        }
        while(!stack.isEmpty())
        {
            System.out.print(stack.pop());
            if(!stack.isEmpty())System.out.print("->");
        }
        System.out.println();
       
       
    }
分享到:
评论

相关推荐

    全国交通咨询系统(数据结构课设 图的应用 java实现 内含课设报告)

    全国交通咨询系统(数据结构课设 图的应用 java实现 内含课设报告)全国交通咨询系统(数据结构课设 图的应用 java实现 内含课设报告)全国交通咨询系统(数据结构课设 图的应用 java实现 内含课设报告)全国交通...

    java-数据结构代码实现

    本资料包“java-数据结构代码实现”提供了使用Java语言实现数据结构的实例,旨在帮助开发者加深对数据结构的理解并提升编程技能。 1. **链表**:链表是一种动态数据结构,其元素在内存中不是顺序排列的。Java中的...

    数据结构图方法包java语言

    数据结构图方法包是计算机科学中的重要组成部分,特别是在Java编程中。这个包涵盖了图的各种操作,包括图的存储、遍历、以及优化算法。以下是基于标题和描述的详细知识点: 1. **图的表示法**: - **邻接表**:在...

    JAVA版数据结构.pdf

    文中提到了数据结构(Data Structures)和Java语言的结合,这表明文档可能涉及数据结构在Java中的实现方式,包括基本的结构如数组、链表、栈、队列、树和图等,以及它们的特性、操作方法和应用场景。 2. Java中的...

    JAVA 实现数据结构

    本资料包“JAVA 实现数据结构”似乎是一个全面的学习资源,包含了一系列与数据结构相关的Java实现代码。以下是基于文件名的各数据结构详解: 1. **make_tar**: 这个文件可能涉及到创建或处理tar文件,这是一种用于...

    DICOM医学图像数据接口的Java实现

    这个标准定义了数据结构、通信协议和文件格式,使得不同厂商的医疗设备和软件能够共享医学图像数据。在Java中实现DICOM接口,可以让我们构建跨平台的医学图像处理应用。 在Java中实现DICOM接口,首先需要理解DICOM...

    java实现各种数据统计图

    在Java编程环境中,实现数据统计图是一项常见的任务,特别是在数据分析、可视化报告或用户界面设计中。JFreeChart是一个强大的开源库,它为开发者提供了丰富的图表类型,如柱形图、饼图和折线图,使得在Java中创建...

    java实现的数据结构与算法

    《Java实现的数据结构与算法》是一本全面介绍数据结构和算法实现的书籍,以Java语言为载体,涵盖了面向对象程序设计的基本概念和特性,并深入探讨了数据结构与算法的方方面面,包括各种数据结构的基本概念、算法的...

    java数据结构实例

    在这个压缩包文件中,我们可以预期找到一些用Java实现的数据结构的源代码。 数据结构是计算机存储、组织数据的方式,它决定了数据的逻辑结构、存储结构以及数据的操作。在Java中,常见的数据结构包括数组、链表、栈...

    java 实现饼状图、柱状图、折线图

    本篇文章将详细探讨如何使用Java实现这三种图表。 首先,饼状图(Pie Chart)常用于表示各部分占整体的比例。在Java中,我们可以使用JavaFX或JFreeChart库来创建饼状图。JavaFX的`PieChart`类提供了直接创建饼图的...

    Java数据结构课件

    Java作为一门面向对象的编程语言,提供了丰富的类库来支持这些数据结构的实现。 在Java中,数组是最基本的数据结构,它允许存储同类型的元素序列。数组提供了直接访问元素的能力,但插入和删除元素的效率较低。链表...

    Java版本数据结构实验报告

    总的来说,"Java版本数据结构实验报告"是一个全面的学习资源,它涵盖了数据结构的基本理论和Java实现,旨在提升学生的算法思维能力和编程技巧。通过这一系列的实验,学生不仅能熟练掌握各种数据结构,还能学会如何...

    java数据结构与算法.pdf

    Java作为广泛应用的编程语言,其在实现数据结构和算法时有着丰富的库支持和优秀的可读性。下面将对标题和描述中提到的一些关键知识点进行详细解释。 1. **数据结构**: - **稀疏数组**:当大量数据中大部分为零或...

    数据结构与算法代码详解JAVA版

    本资源"数据结构与算法代码详解JAVA版"聚焦于使用Java语言来理解和实现这些核心概念。 首先,数据结构是组织和存储数据的方式,它为高效地执行各种操作提供了便利。常见的数据结构包括数组、链表、栈、队列、树(如...

    Java版数据结构(程序员必须看)

    在Java这样的面向对象语言中,数据结构和算法的实现往往涉及到数据类型的使用。Java提供了丰富的数据类型,包括基本类型(如int、float)和构造类型(如数组、类)。数据对象是某种数据类型的元素集合,而数据结构则...

    数据结构(java版本)

    《数据结构(Java版本)》这本书正是为此目的而编写,旨在将理论与实际编程相结合,通过Java语言来实现各种经典的数据结构。 首先,书中的基础部分会介绍数据结构的基本概念,如数组、链表、栈和队列。数组是最基本...

    java实现各种数据统计图(柱形图,饼图,折线图).zip

    Java是一种广泛使用的编程语言,尤其在企业级应用和数据分析领域。在Java中,为了呈现数据可视化,我们可以利用库如JFreeChart。JFreeChart是一个强大的图表库,它提供了丰富的图表类型,包括柱形图、饼图和折线图,...

    Java数据结构和算法中文第二版_Java数据结构_

    《Java数据结构和算法中文第二版》是一本深入探讨Java编程中数据结构和算法的书籍。数据结构是计算机科学的基础,它涉及到如何有效地组织和存储数据,以便在各种操作下高效地访问和修改。算法则是解决问题的具体步骤...

    java语言数据结构

    4. **ch04**:可能涵盖了排序算法,如冒泡排序、插入排序、选择排序、快速排序、归并排序等,以及它们的Java实现和性能分析。 5. **ch05**:可能会讨论堆(堆排序、优先队列)和哈希表。哈希表提供了快速的查找、...

    邓俊辉版java 数据结构源码

    《邓俊辉版Java数据结构源码》是学习数据结构与算法的重要参考资料,它与邓俊辉教授编写的《Java数据结构》教材相配套,旨在帮助读者深入理解数据结构的概念和实现方法。邓俊辉教授的讲解风格清晰易懂,他的源码同样...

Global site tag (gtag.js) - Google Analytics