6. C#数据结构与算法 -- 非线性结构(图)

图表示点之间的关系,在C#中通过节点对象的集合来表示点(Vertex),用邻接矩阵(adjacency matrix)来表示点之间的关系。下面来看C#实现。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Graph
{
    //表示点的类
    //每个节点包含两个字段,分别为节点数据以及表示是否被访问过的一个布尔类型。
    class Vertex
{
        public string Data;
        public bool IsVisited;
        public Vertex(string Vertexdata)
{
                Data = Vertexdata;
}
}
    //表示图的类
    //图中除了需要点的集合和邻接矩阵之外,还需要一些基本的向图中添加或删除元素的方法,以及一个构造方法来对图进行初始化。
    public class Graph
{
        //图中所能包含的点的上限
        public const int Number = 10;
        //顶点数组
        private  Vertex[] vertiexes;
        //邻接矩阵
        public int[,] adjmatrix;
        //统计当前图中有几个点
        int numVerts = 0;
        //初始化图
        public Graph()
{
            //初始化邻接矩阵和顶点数组
            adjmatrix = new Int32 [Number,Number];
            vertiexes = new Vertex[Number];
            //将代表邻接矩阵的表全初始化为0
            for (int i = 0; i < Number;i++ )
{
                for (int j = 0; j < Number; j++)
{
                adjmatrix[i, j] = 0;
}
}
        }//end Graph()
        //向图中添加节点
        public void AddVertex(string v)
{
            vertiexes[numVerts] = new Vertex(v);
                numVerts++;
}
        //向图中添加有向边
        public void AddEdge(int vertex1, int vertex2)
{
                adjmatrix[vertex1,vertex2]=1;
}
        //end AddEdge()
        //显示点
        public void DisplayVert(int vertexPosition)
{
            Console.Write(vertiexes[vertexPosition].Data+" ");
}
 
        /***拓扑排序:找到没有后继节点的节点,删除,加入一个栈,然后输出***/
        /**
* 拓扑排序(TopSort)
拓扑排序是对一个有向的,并且不是环路的图中所有的顶点线性化。需要如下几个步骤
1.首先找到没有后继的节点。
2.将这个节点加入线性栈中
3.在图中删除这个节点
4.重复步骤1,2,3
* */
        //1. 首先需要找到后继节点的方法:
        //寻找图中没有后继节点的点
        //具体表现为邻接矩阵中某一列全为0
        //此时返回行号,如果找不到返回-1
        public int FindNoSuccessor()
{
            bool isEdge;
            //循环行
            for (int i = 0; i < numVerts; i++)
{
                isEdge = false;
                //循环列,有一个1就跳出循环
                for (int j = 0; j < numVerts; j++ )
{
                    if (adjmatrix[i, j] == 1)
{
                        isEdge = true;
                        break;
}
}
                if (!isEdge)
{
                    return i;
}
}
                return -1;
        }//end FindNoSuccessor()
        //3. 删除图中的点
        // 此外还需要删除图中点的方法,这个方法不仅需要删除图中对应位置的点,还需要删除邻接矩阵对应的行和列,因此设置了两个辅助方法,见代码。
        // 需要两个操作,分别从数组中删除点
        // 从邻接矩阵中消去被删点的行和列
        public void DelVertex(int vert)
{
            //保证不越界
            if(vert <= numVerts -1)
{
                //删除点
                for (int i = vert; i < numVerts; i++)
{
                vertiexes[i] = vertiexes[i + 1];
}
                //删除邻接矩阵的行
                for (int j = vert; j < numVerts; j++)
{
                MoveRow(j, numVerts);
}
                //删除邻接矩阵中的列,因为已经删了行,所以少一列
                for (int k = vert; k < numVerts - 1; k++)
{
                MoveCol(k,numVerts-1);
}
                //删除后减少一个
                numVerts--;
}
        }//end DelVertex()
        //辅助方法,移动邻接矩阵中的行
        public void MoveRow(int row, int length)
{
            for (int col = row; col < numVerts; col++)
{
                adjmatrix[row, col] = adjmatrix[row+1, col];
}
        }// end MoveCol()
        //辅助方法,移动邻接矩阵中的列
        public void MoveCol(int col, int length)
{
            for (int row = col; row < numVerts; row++)
{
adjmatrix[row, col] = adjmatrix[row, col + 1];
}

        }// end MoveCol()
        //拓扑排序
        //找到没有后继节点的节点,删除,加入一个栈,然后输出
        public void TopSort()
{
            int origVerts = numVerts;
            //存放返回节点的栈
            Stack result = new Stack();
            while (numVerts > 0)
{
                //找到第一个没有后继节点的节点
                int currVertex = FindNoSuccessor();
                if (currVertex == -1)
{
                    Console.WriteLine("the graph is a ring, can not do Topsort().");
                    return;
}
                //如果找到,将其加入返回结果栈
                result.Push(vertiexes [currVertex].Data);
                //然后删除此节点
                DelVertex(currVertex);
}
            //输出排序后的结果
            Console.Write("this is the Topsort():");
            while (result.Count > 0)
{
                Console.Write(result.Pop()+" ");
}

        }//end TopSort()
        //图的遍历
        //很多时候,我们需要知道从图中给定点到另一个点是否能走通,比如几个车站之间是否可以连接。
        //这时我们需要对图进行查找,查找大概可以分为两类,深度优先遍历和广度优先遍历
        //1.深度优先遍历(Depth-First Search)
        //深度优先遍历首先从一个点开始,到一条路径结束,然后循环找第二条路径,到结束,依此往复。
        //首先我们需要一个辅助方法返回给定的点最近一个连接并且未被访问过的序号。
        //从邻接矩阵查找给定点第一个相邻且未被访问过的点
        //参数v是igeiding在邻接矩阵的行
        public int GetAdjUnvisitedVertex(int v)
{
            for (int j = 0; j < numVerts; j++)
{
                if (adjmatrix[v, j] == 1 && vertiexes[j].IsVisited == false)
{
                    return j;
}
}
            return -1;
        }//end GetAdjUnivisitedVertex()
        //深度优先遍历
        public void DeptFirstSearch()
{
            //声明一个存储临时结果的栈
            Stack s = new Stack();
            //先访问第一个节点
            vertiexes[0].IsVisited = true;
                DisplayVert(0);
                s.Push(0);
            int v;
            while (s.Count > 0)
{
                //获得和当前节点连接的未访问过节点的序号
                v = GetAdjUnvisitedVertex((int)s.Peek());
                if (v == -1)
{
                s.Pop();
}
                else
{
                    //标记为已经被访问过
                    vertiexes[v].IsVisited = true;
                DisplayVert(v);
                s.Push(v);
}
}
            //重置所有节点为未访问过
            for (int u = 0; u < numVerts; u++)
{
                vertiexes[u].IsVisited = false;
}
}
        //end 深度优先遍历
 
       // 广度优先遍历(Breadth-First Search)
       // 广度优先遍历首先遍历层级。算法如下:
        public void BreadthFirstSearch()
{
            System.Collections.Queue q = new Queue();
            /*首先访问第一个节点*/
            vertiexes[0].IsVisited = true;
                DisplayVert(0);
                q.Enqueue(0);
            /*第一个节点访问结束*/
            int vert1, vert2;
            while (q.Count > 0)
{
                /*首先访问同层级第一个节点*/
                vert1 = (int)q.Dequeue();
                vert2 = GetAdjUnvisitedVertex(vert1);
                /*结束*/
                while (vert2 != -1)
{
                    /*首先访问第二个节点*/
                    vertiexes[vert2].IsVisited = true;
                        DisplayVert(vert2);
                        q.Enqueue(vert2);
                    //寻找邻接的
                        vert2 = GetAdjUnvisitedVertex(vert1);
}
}
            //重置所有节点为未访问过
            for (int u = 0; u < numVerts; u++)
{
                vertiexes[u].IsVisited = false;
}
 
        } //end 广度优先遍历
 
        //end 图的遍历
}
    class Program
{
        //代码实现
        static void Main(string[] args)
{

            ////建立图,测试拓扑排序
            //Graph g = new Graph();
            ////向图添加点
            //g.AddVertex("A");
            //g.AddVertex("B");
            //g.AddVertex("C");
            //g.AddVertex("D");
            ////向图添加边
            //g.AddEdge(0,1);
            //g.AddEdge(1, 2);
            //g.AddEdge(2, 3);
            //g.AddEdge(3, 4);

            ////对图进行拓扑排序
            ////g.TopSort();

            ////结果: this is the Topsort(): A B C D 
 
            //建立图,测试图的遍历广度优先,深度优先
            Graph g = new Graph();
            g.AddVertex("A");
            g.AddVertex("B");
            g.AddVertex("C");
            g.AddVertex("D");
            g.AddVertex("E");
            g.AddVertex("F");
            g.AddVertex("G");
            g.AddEdge(0, 1);
            g.AddEdge(0, 2);
            g.AddEdge(1, 3);
            g.AddEdge(2, 4);
            g.AddEdge(3, 5);
            g.AddEdge(4, 6);
            Console.WriteLine("DeptFirstSearch:");
            g.DeptFirstSearch();
            ///结果: DeptFirstSearch: A B D F C E G
            Console.WriteLine();
            Console.WriteLine("BreadthFirstSearch:");
            g.BreadthFirstSearch();
            ///结果: DeptFirstSearch: A B C D E F G
            Console.ReadLine();
 
}
}
}

参考:
http://www.cnblogs.com/CareySon/archive/2012/04/20/ImpleGraphWithCSharp.html

时间: 2024-10-12 18:03:30

6. C#数据结构与算法 -- 非线性结构(图)的相关文章

学好数据结构和算法 —— 非线性结构(上)

序言 上篇讲到线性结构,和线性结构相反的是非线性结构,非线性结构特点是一个结点元素可能有多个直接前驱和多个直接后继.常见的非线性结构有:二(多)维数组.树.图. 本来计划是非线性结构作为一篇,写着写着发现内容确实太多了,拆分为上.中.下3篇比较合适,所以改变了之前的计划. 1.二维数组 如:a[0][0]在水平方向有后继a[0][1],垂直方向有后继a[1][0],二维数组从水平方向或垂直方向看,某个元素都有前驱或后继,并不是线性结构. 二维数组的表示方法 矩阵表示法 行向量表示法 列向量表示法

4、非线性结构--图——数据结构【基础篇】

非线性结构--图 图的几个类别: 有向图 --有向图采用<>表示 无向图--无向图采用()表示 完全图无向图--如果具有n个顶点,n(n-1)/2条边的图 完全图有向图--如果具有n个顶点,n(n-1)条弧的图 稀疏图--如果边数小于完全图的边数 稠密图--如果边数大于完全图的边数 图的几个基本概念: 度--在图中,一个顶点依附的边数或弧的数目,某个顶点的出度和入度之和称为该顶点的度 入度--在图中,一个顶点依附的弧头数目 出度--在图中,一个顶点依附的弧尾数目 图的存贮结构: 1.图的邻接矩

js数据结构与算法存储结构

数据结构(程序设计=数据结构+算法) 数据结构就是关系,没错,就是数据元素相互之间存在的一种或多种特定关系的集合. 传统上,我们把数据结构分为逻辑结构和物理结构. 逻辑结构:是指数据对象中数据元素之间的相互关系,也是我们今后最需要关注和讨论的问题. 物理结构:是指数据的逻辑结构在计算机中的存储形式. 常用的数据结构有: 数组,队列(queue),堆(heap),栈(stack),链表(linked list ),树(tree),图(graph)和散列表(hash) 栈(stack):运算只在表的

13. C#数据结构与算法 -- 线性结构

本文中,我们讨论了三个部分的内容: 什么是线性结构,线性结构有哪些特点 . 详细介绍了一个最简单线性结构顺序表,并且通过源代码进行一些的分析. 最后还举了一个例子,让我们更好的理解顺序表. 第一部分:什么是线性结构,线性结构有哪些特点 什么是线性结构,线性结构是最简单.最基本.最常用的数据结构.线性表是线性结构的抽象(Abstract), 线性结构的特点是结构中的数据元素之间存在一对一的线性关系. 这 种一对一的关系指的是数据元素之间的位置关系,即: (1)除第一个位置的数据元素外,其它数据元素

数据结构与算法之十一 图

目标. 在本章中,你将学习到: 图相关的概念 实现图 应用图解决编程问题 考虑一种情况: 你必须访问一系列城市并且在结束的时候返回原来的城市. 对此,你需要: 找到最短或花费最少的路径,它开始于当前的城市,访问每一个预期的城市,然后返回原来的城市. 你如何解决此问题? 要解决此问题,你需要: 确定属于不同城市的信息的表示方式和城市间的距离的表示方式. 这种关系可以在图中表示. 图被定义为一种数据结构,它由一系列顶点(节点)和边(弧)组成. 它是数据项(顶点)的集合,这些数据项被相互连接以形成网络

数据结构和算法思维导图

需要重点以下10种数据结构和10种算法: 10 个数据结构:数组.链表.栈.队列.散列表.二叉树.堆.跳表.图.Trie 树 10 个算法:递归.排序.二分查找.搜索.哈希算法.贪心算法.分治算法.回溯算法.动态规划.字符串匹配算法 原文地址:https://www.cnblogs.com/gaopengpy/p/12276035.html

python数据结构与算法——二叉树结构与遍历方法

先序遍历,中序遍历,后序遍历 ,区别在于三条核心语句的位置 层序遍历  采用队列的遍历操作第一次访问根,在访问根的左孩子,接着访问根的有孩子,然后下一层 自左向右一一访问同层的结点 # 先序遍历 # 访问结点,遍历左子树,如果左子树为空,则遍历右子树, # 如果右子树为空,则向上走到一个可以向右走的结点,继续该过程 preorder(t):    if t:       print t.value       preorder t.L       preorder t.R # 中序遍历 # 从根

7. C#数据结构与算法 -- 存储结构(单链表)

C#定义并实现单链表 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Linked {     //单链表结点类,采用泛型       public class Node<T> {         private T data; //数据域,当前结点的数据           private 

7-4-无向图的邻接多重表存储结构-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 无向图的邻接多重表存储结构 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c.LinkQueue.c