关于树结构的非线性表编程在数据结构中可以说占据了半壁江山,其中涉及的知识点繁杂,但也是数据结构体现运算优化的核心所在,下面我们将较为初步且系统得讨论数据结构中一系列有关树的表示。

首先我们再次明确树的形式化概念:

树是n个节点的有限集合,这个集合满足以下的条件:

1)     有且仅有一个节点没有前件。

2)     除根外,其他的所有节点都有且仅有一个前件。

3)     除去根以外,其他每个节点都通过唯一的路径连接根上。每个节点的前件称为该节点的父节点,后件称为该节点的子节点。

这篇文章主要包含如下4个知识点:

(1)   用树的遍历求解层次性问题。

(2)   用树结构支持并查集。

(3)   用树状数组同济子树权和。

(4)   用四叉树求解二维空间问题。

首先我们讨论树在计算机中的表示,这不仅仅在处理一些数据结构的题目中很重要,在一些树形动态规划的问题上,我们首先要完成的也是树的表示。

方法1:双亲表示法。

在高级语言中我们容易操作和定义的是线性结构,即数组这样的数据结构,因此我们考虑非线性结构的程序语言表示的时候,基本原则就是将其向线性数据结构转化。给出一个树结构,根据树的定义我们知道,除了根节点,每个节点有且仅有一个父节点。因此我们定义双亲表示数组f[].其中f[i]表示节点i的父节点的节点序号。

方法2:多重链表法

这里我们常常用到c++语言stl库中的vector类。对于给定的一棵树,我们利用”vector<int> tree[n]”这样一条语句,然后定义tree[i].push_back(j)表示j作为i的一个子节点。通俗来说,这里我们将树结构扩成了一个二维数组,而利用vector类则是为了更好的节约空间资源。

一般题目中,输入的树结构往往是对于给定的n个节点的树结构,输入n-1个有序节点对用于表示父子关系,这时候往往用方法2表示树是比较常见的,而往往在一般题目中,需要多种表示方法并用,因为各个树结构的表示方式都有各自的优点(访问树自身某方面的信息时比较快)。

用树的遍历求解层次性问题:

最近公共祖先问题:

给出一个n节点的树结构的n-1对有序顶点对<x , y>,表示树结构中的一条边且x是父节点,y是子节点。最后输入一对节点序号<a, b>,编写程序

最近公共祖先代码如下:

//poj 1330.

#include<cstdio>

#include<cstring>

#include<vector>

using namespace std;

const int N = ;

vector<int > a[N];

int f[N] , r[N];

void DFS(int u , int dep)//从dep层的u节点处罚,先序遍历计算每个节点的层次

{

    r[u] = dep;

    for(vector<int>::iterator it = a[u].begin();it != a[u].end();++it){

        DFS(*it , dep + );

    }

}

int main(){

   int casenum , num , n , i , x , y;

   scanf("%d" , &casenum);

   for(num = ;num < casenum;num++){

     scanf("%d" , &n);

     for(i = ;i < n;i++) a[i].clear();

     memset(f , - , sizeof(f));

     for(i = ;i < n - ;i++){//n个节点的树 , n-1条边

           scanf("%d %d" , &x , &y);//树种的一个边<x , y>,x是父节点,y是子节点;

           x--;y--;

           a[x].push_back(y);

           f[y] = x;

     }

     for(i = ;f[i] >= ;i++);

     DFS(i , );

     scanf("%d %d" , &x , &y);

     x--;y--;

     while(x != y){

        if(r[x] > r[y])  x = f[x];

        else             y = f[y];

     }

     printf("%d\n" , x + );

   }

}

用树结构支持并查集:

在一般的数据结构的教材中,集合与图、树一样,都是群聚类的非线性表,但是集合更加侧重于包含关系而忽略一个集合中各个元素之间的前后件关系。在一些问题中,我们需要将n个元素划分成若干组,每个组视为一个集合,通常需要涉及集合的合并与查找,因此我们称其为并查集。

并查集需要支持如下的操作:

(1)   Make_set(x):加入单个元素x到集合S中。

(2)   Join(x,y),把x、y所在的不同集合进行合并。

(3)   Set_find(x):得到x所在集合S的代表元。

下面我们来讨论并查集的存储结构。理论上来说,并查集有链结构和树结构两种,但是树结构在完成各个操作时的效率更加优良,我们便直接介绍树结构。

我们用一棵树结构表示集合S={s1,s2,s3,…,sn}.由于我们仅仅是用树结构来表示集合,因此这棵树中的边关系,仅仅是体现了合并操作的前后顺序,边关系不同时,所表达的集合是完全等价的。紧接着,由于树结构依然不能直接存储,我们还要想办法将其转化成线性存储结构。我们如何来表征这样一个集合的特征呢?我们选择一个集合的代表元(也就是树结构表示的并查集的根节点),我们定义set[x]表示元素x所在集合的代表元,而如果x是集合S的代表元,则令set[x] = -1(这种表示方法可以理解为并查集 -> 树结构表示 -> 双亲表示法).那么基于这样的定义,我们能够看到,set[x]与 set[y]的相等关系便可以作为两个元素x、y是否在同一集合的指标了。

查找过程:

对于给出的元素x,我们想要找到x所在集合的代表元,也可以说成是x所在树结构的根节点。直接访问set[x]我们发现存在这样一个问题,x的根节点y在某一次合并操作之后合并到了一个更大的集合,原本是根节点的y变成了树结构中的分支节点,因此我们需要沿树结构继续向上找,我们会遇到相同的问题,因此需要设计一个递归机制。同时为了以后访问的方便,我们采用路径压缩的手法,来使得从x出发找到根节点r的路径经过的所有节点i的set[i]都变成r.

int set_find(int p){

if(set[p] < ) return p; //找到根节点/集合代表元

return set[p] = set_find(set[p]);

}

合并过程:

合并过程就显得很简单,假设我们想要合并元素x、y所在集合,我们只需要分别找到x、y所在集合的代表元p , q,使set[p] = q即可,当然yekeyi 交换p、q的位置。即从x、y所在集合的代表元中选择任意一个成为新的集合的代表元。

void join(int x , y){

  p = set_find(p);

  q = set_find(q)

  if(p != q)

  set[q] = p;

}

数据结构编程实验——chapter8-采用树结构的非线性表编程的更多相关文章

  1. 【Unix网络编程】chapter8基本UDP套接字编程

    chapter8基本UDP套接字编程 8.1 概述 典型的UDP客户端/服务端的函数调用 8.2 recvfrom和sendto函数 #include <sys/socket.h> ssi ...

  2. 数据结构编程实验——chapter9-应用二叉树的基本概念编程

    二叉树是树结构中的重要概念,一些特殊的二叉树如满二叉树和完全二叉树由于节点序号的特殊关系,在一些算法中十分常见. 这篇文章将从三个方面介绍有关二叉树的知识点: (1)   普通有序树转化为二叉树. ( ...

  3. 20172301 《Java软件结构与数据结构》实验二报告

    20172301 <Java软件结构与数据结构>实验二报告 课程:<Java软件结构与数据结构> 班级: 1723 姓名: 郭恺 学号:20172301 实验教师:王志强老师 ...

  4. 2017-2018-2 1723《程序设计与数据结构》实验四 & 实验五 & 课程总结 总结

    作业地址 实验四作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1943 提交情况如图: 实验五作业:https://edu ...

  5. 用Python做2048游戏 网易云课堂配套实验课。通过GUI来体验编程的乐趣。

    第1节 认识wxpython 第2节 画几个形状 第3节 再做个计算器 第4节 最后实现个2048游戏 实验1-认识wxpython 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiy ...

  6. 20172328《程序设计与数据结构》实验四 Android程序设计报告

    20172328<程序设计与数据结构>实验四 Android程序设计报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 李馨雨 学号:20172328 实验教师:王志 ...

  7. 20172328《程序设计与数据结构》实验三 敏捷开发与XP实践报告

    20172328<程序设计与数据结构>实验三 敏捷开发与XP实践报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 李馨雨 学号:20172328 实验教师:王志强 ...

  8. 20172310 2017-2018-2 《程序设计与数据结构》实验三报告(敏捷开发与XP实践)

    20172310 2017-2018-2 <程序设计与数据结构>实验三报告(敏捷开发与XP实践) 课程:<程序设计与数据结构> 班级: 1723 姓名: 仇夏 学号:20172 ...

  9. 20172301 《Java软件结构与数据结构》实验三报告

    20172301 <Java软件结构与数据结构>实验三报告 课程:<Java软件结构与数据结构> 班级: 1723 姓名: 郭恺 学号:20172301 实验教师:王志强老师 ...

随机推荐

  1. BETA随笔6/7

    前言 我们居然又冲刺了·六 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 过去两天完成了哪些任务 新方案代码比之前的更简单,但是对场景的要求相应变高了,已经实现,误差感人 代码 ...

  2. BETA-4

    前言 我们居然又冲刺了·四 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 过去两天完成了哪些任务 整理了一丢丢代码 接下来的计划 认真复习准备考试,挤时间把软工搞定 还剩下哪些 ...

  3. ACM Shenyang Onsite 2016 题目

    A. Thickest Burger 1000ms 262144K   ACM ICPC is launching a thick burger. The thickness (or the heig ...

  4. 转 理解vuex -- vue的状态管理模式

    转自:https://segmentfault.com/a/1190000012015742 vuex是什么? 先引用vuex官网的话: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 ...

  5. 评论各组alpha发布

    单纯从用户和体验者的角度来评价. 天天向上组的连连看游戏和新锋组的俄罗斯方块游戏,从alpha发布的成果完成度来看,两个游戏现在都可以玩,但连连看的完成度更高,可选背景,可选音乐.俄罗斯方块还有其他界 ...

  6. webservice(一) 概念

    Web service:是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些应用程序,用于开发分 ...

  7. notepad++ 安装go插件

    1. 想学习go语言 使用notepad++ 但是发现无法安装 gonpp的插件 花了很长时间. 发现问题为: 前几天将notepad++ 升级到了 7.6 的版本 然后使用 plugin manag ...

  8. 内存映像分析工具Eclipse Memory Analyzer

    1. Eclipse Memory Analyzer安装 Help ->Eclipse Marketplace,搜索Memory,点击install,->confirm->同意证书内 ...

  9. Spring、MyBatis和SpringMVC整合的jar包下载

    spring mvc的jar包下载:http://repo.springsource.org/libs-release-local/org/springframework/spring/我下载的5.0 ...

  10. windows和Ubantu双系统安装图解

    Win7 U盘安装Ubuntu16.04 双系统详细教程 安装主要分为以下几步: 一. 下载Ubuntu 16.04镜像软件: 二. 制作U盘启动盘使用ultraISO: 三. 安装Ubuntu系统: ...