树的概念

形式化定义:算法的集合树(Tree)是由一个或多个结点组成的有限集合T,其中有一个特定的称为根的结点;其余结点可分为(m≥0)个互不相交的有限集T1,T2,T3,…,Tm,每一个集合本身又是一棵树,且称为根的子树。

逻辑结构:

树的表示

  • 图形表示法
  • 表表示法:(A(B(E,F),C(G),D(H,I,J)))

树的术语

  • 结点的度:结点子树个数为结点的度
  • 树的度:树中结点度的最大值
  • 森林:0棵或多棵不相交的树的集合

树的存储结构可以采用具有多个指针域的多重链表,结点中指针域的个数应由树的度来决定。

二叉树

定义:二叉树是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵不相交的左子树和右子树组成。

特点

  • 在二叉树中,不存在度大于2的结点;
  • 二叉树是有序树(树为无序树),其子树的顺序不能颠倒。

基本形态:二叉树有五种不同的形态。

满二叉树:深度为k具有个结点的二叉树,称为满二叉树。

完全二叉树:如果一棵具有n个结点的深度为k的二叉树,它的每一个结点都与深度为k的满二叉树中编号为1~n的结点一一对应,则称这棵二叉树为完全二叉树。完全二叉树又称为顺序二叉树。

性质

  • 若二叉树的层数从1开始,则二叉树的第k层结点数,最多为个(k≥1)。

  • 深度(高度)为k的二叉树最多结点数为(k≥1)。
  • 若对任意一棵二叉树,如果叶子结点(度为0)个数为,度为2的结点个数为,则有
  • 具有n个结点的完全二叉树高度为

遍历二叉树:令L,R,T分别代表二叉树的左子树、右子树、根结点,若规定二叉树中必须先左后右(左右顺序不能颠倒),则只有TLR、LTR、LRT三种遍历规则。

  • TLR称为前根遍历(或前序遍历、先序遍历、先根遍历)
  • LTR称为中根遍历(或中序遍历)
  • LRT称为后根遍历(或后序遍历)

二叉树的存储结构:

  • 顺序存贮结构:将一棵二叉树按完全二叉树顺序存放到一个一维数组中。
  • 二叉链表存贮结构:将对于非完全二叉树,宜采用链式存储结构。

二叉树例程:

/*** 二叉树* @author wangfei**/
public class TestBinaryTree {public static void main(String[] args) {//创建一棵树BinaryTree binaryTree = new BinaryTree();//创建一个根节点Node root = new Node(1);//把根节点赋值给树binaryTree.setRoot(root);//创建一个左节点Node rootL = new Node(2);//把新创建的节点设置为根节点的子节点root.setLeftNode(rootL);//创建一个右节点Node rootR = new Node(3);//把新创建的节点设置为根节点的子节点root.setRightNode(rootR);//为第二层创建两个子节点root.setLeftNode(new Node(4));root.setRightNode(new Node(5));//前序遍历树binaryTree.frontShow();System.out.println("===========================");//中序遍历树binaryTree.midShow();System.out.println("===========================");//后序遍历树binaryTree.afterShow();System.out.println("===========================");//前序查找Node result = binaryTree.frontSearch(5);System.out.println(result);System.out.println("===========================");//删除一个子树binaryTree.delete(4);binaryTree.frontShow();}}
public class BinaryTree {Node root;//设置根节点public void setRoot(Node root) {this.root = root;}//获取根节点public Node getRoot(Node root) {return root;}//前序遍历public void frontShow() {if(root!=null) {root.frontShow();}}//中序遍历public void midShow() {if(root!=null) {root.midShow();}}//后序遍历public void afterShow() {if(root!=null) {root.afterShow();}}//前序查找public Node frontSearch(int i) {return root.frontSearch(i);}//删除一个子树public void delete(int i) {if(root.value==i) {root = null;}else {root.delete(i);}}
}
public class Node {//节点的权int value;//左儿子Node leftNode;//右儿子Node rightNode;public Node(int value) {this.value = value;}//设置左儿子public void setLeftNode(Node leftNode) {this.leftNode = leftNode;}//设置右儿子public void setRightNode(Node rightNode) {this.rightNode = rightNode;}//前序遍历public void frontShow() {//先遍历当前节点内容System.out.println(value);//左节点if(leftNode!=null) {leftNode.frontShow();}//右节点if(rightNode!=null) {rightNode.frontShow();}}//中序遍历public void midShow() {//左子节点if(leftNode!=null) {leftNode.midShow();}//当前节点System.out.println(value);//右子节点if(rightNode!=null) {rightNode.midShow();}}//后序遍历public void afterShow() {//左子节点if(leftNode!=null) {leftNode.afterShow();}//右子节点if(rightNode!=null) {rightNode.afterShow();}//当前节点System.out.println(value);}//前序查找public Node frontSearch(int i) {Node target = null;//对比当前节点的值if(this.value==i) {return this;//当前节点的值不是要查找的节点}else {//查找左儿子if(leftNode!=null) {//查不到的话,target还是nulltarget = leftNode.frontSearch(i);}//如果不为空,说明在左儿子中已经找到if(target!=null) {return target;}//查找右儿子if(rightNode!=null) {target = rightNode.frontSearch(i);}}return target;}//删除节点public void delete(int i) {Node parent = this;//判断左儿子if(parent.leftNode!=null && parent.leftNode.value==i) {parent.leftNode = null;return;}//判断右儿子if(parent.rightNode!=null && parent.rightNode.value==i) {parent.rightNode = null;return;}//递归检查并删除左儿子parent = leftNode;if(parent!=null) {parent.delete(i);}//递归检查并删除右儿子parent = rightNode;if(parent!=null) {parent.delete(i);}}
}

图的概念

定义图是由顶点集V和顶点间的关系集合E(边的集合)组成的一种数据结构,可以用二元组定义为:G=(V,E)。

有向图和无向图:为新的对话框类添加方在图中,若用箭头标明了边是有方向性的,则称这样的图为有向图,否则称为无向图。

上图可描述为:

G1=(V1,E),V1={a,b,c,d},E1={(a,b),(a,c),(a,d),(b,d),(c,d)}

G2=(V2,E2), V2={1,2,3},E2={<1,2>,<1,3>,<2,3>,<3,1>}

度、入度、出度:具有n个顶点,在图中,一个顶点依附的边或弧的数目,称为该顶点的度。在有向图中,一个顶点依附的弧头数目,称为该顶点的入度。一个顶点依附的弧尾数目,称为该顶点的出度,某个顶点的入度和出度之和称为该顶点的度。

另外,若图中有n个顶点,e条边或弧,第i个顶点的度为di,则有

:若在图的边或弧中给出相关的数,称为权。权可以代表一个顶点到另一个顶点的距离,耗费等,带权图一般称为网。

连通图和非连通图:在无向图中,若任意两个顶点都是连通的,则称此无向图为连通图,否则称为非连通图。

强连通图和非强连通图:在有向图中,若图中任意两个顶点都是连通的,则称此有向图为强连通图,否则称为非强连通图

图的邻接矩阵

定义:

在邻接矩阵表示中,除了存放顶点本身信息外,还用一个矩阵表示各个顶点之间的关系。若(i,j)∈E(G)或〈i,j〉∈E(G),则矩阵中第i行第j列元素值为1,否则为0。

从无向图的邻接矩阵可以得出如下结论:

  • 矩阵是对称的;
  • 第i行或第i列1的个数为顶点i的度;
  • 矩阵中1的个数的一半为图中边的数目;
  • 很容易判断顶点i和顶点j之间是否有边相连(看矩阵中i行j列值是否为1)。

从有向图的邻接矩阵可以得出如下结论:

  • 矩阵不一定是对称的;
  • 第i行中1的个数为顶点i的出度;
  • 第i列中1的个数为顶点i的入度;
  • 矩阵中1的个数为图中弧的数目;
  • 很容易判断顶点i和顶点j是否有弧相连。

图的邻接表

定义:将每个结点的边用一个单链表链接起来,若干个结点可以得到若干个单链表,每个单链表都有一个头结点,所有头结点组成一个一维数组,称这样的链表为邻接表。

从无向图的邻接表可以得到如下结论

  • 第i个链表中结点数目为顶点i的度;
  • 所有链表中结点数目的一半为图中的边数;
  • 占用的存储单元数目为n+2e(e:边数)。

从有向图的邻接表可以得到如下结论

  • 第i个链表中结点数目为顶点i的出度;
  • 所有链表中结点数目为图中弧数;
  • 占用的存储单元数目为n+e。

深度优先搜索思想:深度优先搜索遍历类似于树的先序遍历。假定给定图G的初态是所有顶点均未被访问过,在G中任选一个顶点i作为遍历的初始点,则深度优先搜索遍历可定义如下:

  • 首先访问顶点i,并将其访问标记置为访问过,即visited[i] =1;
  • 然后搜索与顶点i有边相连的下一个顶点j,若j未被访问过,则访问它,并将j的访问标记置为访问过,visited[j]=1,然后从j开始重复此过程,若j已访问,再看与i有边相连的其它顶点;
  • 若与i有边相连的顶点都被访问过,则退回到前一个访问顶点并重复刚才过程,直到图中所有顶点都被访问完止。

广度优先搜索的思想:广度优先搜索遍历类似于树的按层次遍历。设图G的初态是所有顶点均未访问,在G中任选一顶点i作为初始点,则广度优先搜索的基本思想是:

  • 首先访问顶点i,并将其访问标志置为已被访问,即visited[i]=1;
  • 接着依次访问与顶点i有边相连的所有顶点W1,W2,…,Wt;
  • 然后再按顺序访问与W1,W2,…,Wt有边相连又未曾访问过的顶点;
  • 依此类推,直到图中所有顶点都被访问完为止。

图结构例程:

/*** 图* @author wangfei**/
public class Graph {private Vertex[] vertexs;private int currentSize;public int[][] adjMat;private MyStack stack = new MyStack();//当前遍历的下标private int currentIndex;public Graph(int size) {vertexs = new Vertex[size];adjMat = new int[size][size];}/*** 向图中加入一个顶点* @param v*/public void addVertex(Vertex v) {vertexs[currentSize++] = v;}/*** 向相邻顶点添加连接线* @param v1* @param v2*/public void addEdge(String v1, String v2) {//找出两个顶点的下标int index1 = 0;for(int i=0; i<vertexs.length; i++) {if(vertexs[i].getValue().equals(v1)) {index1 = i;break;}}int index2 = 0;for(int i=0; i<vertexs.length; i++) {if(vertexs[i].getValue().equals(v2)) {index2 = i;break;}}adjMat[index1][index2] = 1;adjMat[index2][index1] = 1;}/*** 深度优先搜索算法遍历图*/public void dfs() {//把第0个顶点标记为已访问状态vertexs[0].visited = true;//把第0个元素压入栈中stack.push(0);//打印顶点的值System.out.println(vertexs[0].getValue());//遍历out:while(!stack.isEmpty()) {for(int i=currentIndex; i<vertexs.length; i++) {//如果和下一个遍历的元素是通的if(adjMat[currentIndex][i]==1 && vertexs[i].visited==false) {//把下一个元素压入栈中stack.push(i);vertexs[i].visited = true;System.out.println(vertexs[i].getValue());continue out;}}//弹出栈顶元素stack.pop();//修改当前位置为栈顶元素if(!stack.isEmpty()) {currentIndex = stack.peek();}}}
}
/*** 顶点类* @author wangfei **/
public class Vertex {private String value;public boolean visited;public String getValue() {return value;}public void setValue(String value) {this.value = value;}public Vertex(String value) {super();this.value = value;}@Overridepublic String toString() {return value;}}
public class MyStack {//栈的底层我们使用数组来存储数据int[] elements;public MyStack() {elements = new int[0];}//压入元素public void push(int element) {// 创建一个新的数组int[] newArr = new int[elements.length + 1];// 把原数组中的元素复制到新数组中for (int i = 0; i < elements.length; i++) {newArr[i] = elements[i];}// 把添加的元素放入新数组中newArr[elements.length] = element;// 使用新数组替换旧数组elements = newArr;}//取出栈顶元素public int pop() {//栈中没有元素if(elements.length==0) {throw new RuntimeException("stack is empty");}//取出数组的最后一个元素int element = elements[elements.length-1];//创建一个新的数组int[] newArr = new int[elements.length-1];//原数组中除了最后一个元素的其它元素都放入新的数组中for(int i=0;i<elements.length-1;i++) {newArr[i]=elements[i];}//替换数组elements=newArr;//返回栈顶元素return element;}//查看栈顶元素public int peek() {//栈中没有元素if(elements.length==0) {throw new RuntimeException("stack is empty");}return elements[elements.length-1];}//判断栈是否为空public boolean isEmpty() {return elements.length==0;}}

数据结构与算法 -- 树结构与图结构相关推荐

  1. 一步一步写算法(之图结构)

    原文:一步一步写算法(之图结构) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 图是数据结构里面的重要一章.通过图,我们可以判断两个点之间是 ...

  2. 数据结构与算法思维导图(学习笔记)

    版本 数据结构与算法思维导图V1.0 V1.0分享版本这个可以直接看,不需要下载. 说明 1.free 2.目前内容主要包含内容包含: 数据结构与算法思维导图 包含:线性表.顺序结构.链式结构,栈与队 ...

  3. 数据结构与算法学习笔记——图 C++实现

    数据结构与算法学习笔记--图 C++实现 1 概念 2 图的表示方法 3 算法 3.1 拓扑排序 3.2 图的搜索算法 3.2.1 广度优先搜索(BFS) 3.2.2 深度优先搜索(DFS) 3.3 ...

  4. 数据结构和算法 -- 学习导图

    数据结构和算法 是作为程序员写出高效代码的基础,为了今后的两年在高效代码之路上持续精进,将按照此学习导图进行 算法和数据结构的刻意练习,同时也希望为同样有高效代码追求的伙伴们提供一条学习路径,共同进步 ...

  5. 数据结构与算法:17 图

    17 图 知识结构: 1. 图的基本概念与术语 1.1 图的定义 图由顶点集和边集组成,记为G=(V,E)G=(V,E)G=(V,E). 顶点集:顶点的有穷非空集合,记为V(G)V(G)V(G). 边 ...

  6. python中判断无向图是否有环_数据结构与算法:17 图

    17 图 知识结构: 图1 知识结构 1. 图的基本概念与术语 1.1 图的定义 图由顶点集和边集组成,记为 . 顶点集:顶点的有穷非空集合,记为. 边集:顶点偶对的有穷集合,记为 . 边: 无向边: ...

  7. 数据结构与算法思维导图(目录)

    (小甲鱼)数据结构与算法(全99讲完结版)学习刷完纪念. 下面是总结的学习内容思维导图.

  8. 线性结构、树结构、图结构

    1.数组和顺序表 2.单链表 3.循环链表 4.双向链表 5.队列和栈 6.树结构的特性 7.二叉树的遍历 8.哈夫曼树和哈夫曼编码 9.二叉树排序 10.图结构的特性 11.图的遍历

  9. 数据结构与算法09 之图

    在计算机程序设计中,图是最常用的结构之一.图是一种与树有些相像的数据结构,实际上,从数学意义上说,树是图的一种.然而在计算机程序设计中,图的应用方式与树不同. 前面讨论的数据结构都有一个框架,这个框架 ...

最新文章

  1. 各种 django 静态文件的配置总结【待续】
  2. java 复制excel jxl_java中使用jxl的jar包处理excel的复制,更新等问题。
  3. 把jpg转换成pdf软件
  4. 【数据挖掘笔记四】数据仓库和联机分析处理
  5. NIO 之 Buffer 图解
  6. java main方法调用非静态方法_java中main函数怎么调用外部非static方法
  7. 多线程的全局变量与局部变量
  8. 王道计算机网络 计算机网络体系结构整理 超详细版
  9. nRF51822 硬件复位引脚
  10. 查看mysql中sql语句执行时间
  11. HTML 基础源代码
  12. python-多元线性回归模型
  13. 按键精灵脚本与Total Control手机群控系统的完美结合
  14. 海龟编辑器怎么运行html,怎么使用海龟编辑器
  15. JTextArea:文本域组件
  16. JAVA有percentile函数吗_计算DAX中的PERCENTILE
  17. PHY--PDSCH
  18. 区块链软件公司:区块链赚钱的领域有哪些
  19. 基于gpg的fwknop配置流程
  20. 最优化方法1——各类拓扑空间与强弱紧集、下半收敛问题

热门文章

  1. NIM(1),转载自:雁过无痕
  2. 《大数据数学基础Python版》读书笔记一
  3. vue写前端出现错误:[Vue warn]: Computed property “editableTabs“ was assigned to but it has no setter.
  4. XRecyclerView、Okhttp
  5. 给职场年轻人的一些建议
  6. 网站后台如何判断客户端是来自手机、还是来自电脑?
  7. Sdn - 基础题试水
  8. 第十三周学习周报(20180528-20180603)
  9. 代码随想录——回溯算法
  10. Java遍历Properties的所有的元素,四种方法详细总结的代码实例