数据结构——二叉树概述及其数组(顺序存储)表达法

树与二叉树:

什么是树呢?就是一个节点上会有很多分叉的数据结构。一般的,对于一棵树,我们需要的结构体为一个数据块和几个指针块,这就相当于很多个链表交织在了一起,实际上,链表也可以算是一种特殊的树,而我要讲的,也是一种特殊的树——二叉树。

对于树的各个节点,都有两个属性,称为度(degree),他的意思就是这个节点所拥有的子节点的数量。还有一个属性,称为深度(depth),指节点到根的距离。

什么是二叉树呢?顾名思义,就是度为二的树,它长这样:

如图所示,在链表中我们需要头(head),而在树中我们就需要根(root),A就是这棵二叉树的根,根据二叉树的定义,每个节点指向两个节点,于是B,C被称为A的孩子(child),我们称为子节点,A就是他们的父母(parent),可以称为父节点。因为DEFG后面不再有其他节点,所以我们称他们为叶节点(leaf)。

关于二叉树的其他概念:

一、斜树:就是斜着长的树,比如上图中只留下ABD或者ACG的话就是斜树了。

二、满二叉树:如果所有的节点都存在左子树和又子树,并且所有的叶的深度都相同,那么这个树被称为满二叉树。

三、完全二叉树:我们对二叉树进行编号,比如上图,编为A(1)B(2)C(3)D(4)E(5)F(6)G(7),可以发现,这棵树一共有7个节点(记为n),但是我们如果删除G,那么是6个节点,对于新的这棵树进行遍历,和当它满的时候各点的编号一样,则它是完全二叉树。但是如果拿掉的是F,那么就不是完全二叉树。满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树。

二叉树的性质:

为什么说二叉树特殊呢?因为它有如下的性质:

一、在二叉树的第i层至多有2i-1个节点。

二、深度为k的二叉树最多有2k-1个节点。(注意与第一点的区别,一个是指数为i-1,一个指数为k但整体-1)

三、具有n个节点的完全二叉树的深度为[(log2n)]+1.[]表示取整.

四、对于任意一个编号为n的节点,如果它有子节点,它的左子节点编号为2n,右节点的编号为2n+1。(这条性质很重要,决定了二叉树可以用数组来表示)。

二叉树的遍历:

二叉树主要有三种遍历方法。

1、先序遍历:优先遍历根,然后优先遍历左节点。图中的二叉树先序遍历后的结果为ABDECFG

2、后序遍历:优先访问最底层的左节点,图中的二叉树后序遍历后的结果为DEBFGCA

3、中序遍历:先访问最下层的叶,并且由左子树到父节点到右子树的顺序遍历,图中二叉树中序遍历后的结果为DBEFCGA

二叉树的顺序存储方法:

对于图中的树,它的编号是这样的:A(1)B(2)C(3)D(4)E(5)F(6)G(7),利用性质四,就可以很轻松的建立一棵顺序二叉树。

我们可以把数组中的第一个位置舍弃,因为不方便。我们来看一下如何进行先序输入吧:

void get_tree(char *tree,int sub){
    char t;
    scanf("%c",&t);
    tree[sub]=t;
    if(t==‘#‘)
        return;
    get_tree(tree,2*sub);
    get_tree(tree,2*sub+1);
}

输入#号表示该节点为空,不然的话,永远都输入不完啦!

那么先序输出也就简单了:

void print_tree(char *tree,int sub){
    if(tree[sub]==‘#‘)
        return;
    printf("%c",tree[sub]);
    print_tree(tree,2*sub);
    print_tree(tree,2*sub+1);
}

代码很简洁方便,而且想要某个点的深度只要取该点下标,利用性质三就行了。由于math.h库里面没有log以2为底的函数,所以需要用到换底公式来操作,我就不再多说了。

总体的代码如下:

//二叉树的先序输入与输出
#include <stdio.h>
void get_tree(char*,int);
void print_tree(char*,int);
int main(){
    char tree[1000];
    get_tree(tree,1);
    print_tree(tree,1);
    return 0;
}
void get_tree(char *tree,int sub){
    char t;
    scanf("%c",&t);
    tree[sub]=t;
    if(t==‘#‘)
        return;
    get_tree(tree,2*sub);
    get_tree(tree,2*sub+1);
}
void print_tree(char *tree,int sub){
    if(tree[sub]==‘#‘)
        return;
    printf("%c",tree[sub]);
    print_tree(tree,2*sub);
    print_tree(tree,2*sub+1);
}
时间: 2024-11-03 05:38:44

数据结构——二叉树概述及其数组(顺序存储)表达法的相关文章

C语言实现数据结构串(定长顺序存储表示法)

-------------------------------------------- 定长顺序存储表示法 -------------------------------------------- 存储结构: 使用字符串数组作为存储,定义字符串数组长度为MAXSTRLEN+1(0位置用来存放字符串长度) -------------------------------------------- 操作方法: 字符串赋值 通过将控制台输入的字符串赋值给串S1(从1开始存储),如果字符串长度超过限制,

数组顺序存储二叉树

1.完全二叉树 完全二叉树由于其结构上的特点,通常采用顺序存储方式存储.一棵有n个结点的完全二叉树的所有结点从1到n编号,就得到结点的一个线性系列. 如下图:完全二叉树除最下面一层外,各层都被结点充满了,每一层结点的个数恰好是上一层结点个数的2倍,因此通过一个结点的编号就可以推知它的双亲结点及左,右孩子结点的编号: ① 当 2i ≤ n 时,结点 i 的左孩子是 2i,否则结点i没有左孩子: ② 当 2i+1 ≤ n 时,结点i的右孩子是 2i+1,否则结点i没有右孩子: ③ 当 i ≠ 1 时

数据结构--二叉树(定义与存储结构)

什么是二叉树 是具有n个节点的有限集合,由一个根节点和两棵互不相交二叉树组成.如图 从名字简单理解,就是具有2个树叉的树形结构,当然这不是绝对的,正如上图所示,我也可以只有一个树叉. 二叉树具有五种基本形态: (1)空二叉树 (2)只有一个根结点的二叉树 (3)只有左子树 (4)只有右子树 (5)既有左子树又有右子树 完全二叉树 这种二叉树,是二叉树中常用的专业术语,不是说一个完整的二叉树就是完全二叉树,这种二叉树叫满二叉树,如图 简单理解就像图片中,完全二叉树中每个节点的编号,都能映射到满二叉

Java数据结构与算法之数组

数组特点: 1.大小固定 2.同一数据类型 3.下标访问 4.数据项可重复 Java数据类型:基本类型(int和double)和对象类型.在许多编程语言中,数组也是基本类型.但在Java中把它们当作对象来对待,因此在创建数组时必须使用new操作符. 有序数组与无序数组比较:最主要的好处是查找速度比无序数组快多了.不好的方面是在插入操作中由于所有靠后的数据都需要移动以疼开空间,所以速度较慢.有序数组和无序数组数据中的删除操作都很慢,这是因为数据项必须向前移动来填补已删除数据项的空洞. 数据访问:从

[转]数据结构 二叉树的遍历

/********************************************************************** 二叉树的基本操作 (1)二叉树的数据结构 (2)二叉树的构造 (3)二叉树遍历 :先序,中序,后序 ************************************************************************/ #include <cstdio> #include <cstdlib> const int

【算法与数据结构】哈希表-链地址法

哈希表的链地址法来解决冲突问题 将所有关键字为同义词的记录存储在同一个线性链表中,假设某哈希函数产生的哈希地址在区间[0, m - 1]上,则设立一个至振兴向量 Chain  ChainHash[m]; 数据结构 //链表结点 typedef struct _tagNode { int data; //元素值(关键字) struct _tagNode* next; //下一个结点 }Node, *PNode; //哈希表结点 typedef struct _tagHashTable { //这里

数据结构--图--图的数组存储表示,深度优先搜索遍历和广度优先搜索遍历

图有四种存储结构:数组,邻接表,十字链表,邻接多重表.下面以数组为存储结构来实现图的深度优先搜索遍历和广度优先搜索遍历.其中广度优先搜索遍历中有用到STL中的queue,注意头文件的包含.具体代码如下: //图的数组(邻接矩阵)存储表示和深度优先遍历 const int MAX_VERTEX_NUM=20; //最大顶点数 typedef enum {DG,DN,UDG,UDN} GraphKind ;//(有向图,有向网,无向图,无向网) typedef int VRType; typedef

(编程训练)再回首,数据结构——二叉树的前序、中序、后序遍历(非递归)

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. 可以和(编程训练)再回首,数据结构--二叉树的前序.中序.后序遍历(递归)对比着看 [问题描述] 根据顺序存储结构建立二叉树的二叉链表,并对二叉树进行先序.中序.后序遍历. [基本要求] ·功能:根据顺序存储结构建立二叉树的二叉链表,并进行先序.中序.后序遍历. ·输入:输入二叉树的顺序存储. ·输出:二叉树的先序.中序.后序遍历序

数据结构之线性表(顺序存储结构)

小学生放学都是要按顺序排队的,一个接一个,每个小学生的前后位置是固定的,这样便于迅速清点. 其实这就是一个线性表,从这件事里我们就可以找到很多关于线性表的特性,如 1.线性表是一个序列,它是有顺序的(排队) 2.第一个元素无前驱,最后一个无后继,其他每个元素都有一个前驱和后继(一个接一个) 3.元素是有限的(小学生的个数是有限的) 4.数据类型都相同(都是小学生在排队) 说明白线性表示什么,下面我们直接看线性表的实现 线性表的实现分顺序存储结构和链式存储结构 顺序存储结构: #define LI