数据结构-二叉树
二叉树基本性质
1 二叉树的基本性质
1.1 性质1: 在二叉树的第i层上至多有2^(i-1)个结点(i>0)
1.2 性质2: 深度为k的二叉树至多有2^k - 1个结点(k>0)
1.3 性质3: 对于任何一棵二叉树,若度为2的结点数有n2个,则叶子数(n0)必定为n2+1 (即n0=n2+1) 度为2 数 + 1 = 叶子数
1.4 性质4: 具有n个结点的完全二叉树的深度必为ëëlog2nû+1
1.4.1 (如 log2 (15) 点击 15 log / 2 log =)
1.5 性质5: 对完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i=1 时为根,除外)
1.6 满二叉树 深度为k的数 并且节点数量为 2^k - 1
1.7 完全二叉树 除了最后一层,上面是一颗满二叉树,在最后一层上只缺少右边的若干节点。
二叉树的表示
二叉链表示法
typedef struct BiTNode
{
int data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
三叉链表示法
每个节点有三个指针域,其中两个分别指向子节点(左孩子,右孩子),还有一个指针指向该节点的父节点。
typedef struct TriTNode
{
int data;
//左右孩子指针
struct TriTNode *lchild, *rchild;
struct TriTNode *parent;
}TriTNode, *TriTree;
二叉树的遍历方式
定义:按某条搜索路线来遍历整个二叉树的所有节点。
遍历方法
牢记一种约定,对每个结点的查看都是“先左后右”
限定先左后右,树的遍历有三种实现方案:
根据根的位置不同,叫法不一样
DLR LDR LRD
先序遍历 中序遍历 后序遍历
DLR — 先序遍历,即先根再左再右
LDR — 中序遍历,即先左再根再右
LRD — 后序遍历,即先左再右再根
注:“先、中、后”的意思是指访问的结点D是先于子树出现还是后于子树出现。
从递归的角度看,这三种算法是完全相同的,或者说这三种遍历算法的访问路径是相同的,只是访问结点的时机不同。
二叉树的递归遍历
1 #include<iostream> 2 using namespace std; 3 4 typedef struct BinaryNode 5 { 6 char ch;//数据域 7 8 struct BinaryNode *lchild;//左孩子 9 struct BinaryNode *rchild;//右孩子 10 11 }BN; 12 void PreOrderTraverse(BN* a)//先序遍历 13 { 14 if (a == NULL) 15 { 16 return; 17 } 18 printf("%c ", a->ch); 19 PreOrderTraverse(a->lchild); 20 PreOrderTraverse(a->rchild); 21 } 22 void MisOrderTraverse(BN* a)//中序遍历 23 { 24 if (a == NULL) 25 { 26 return; 27 } 28 PreOrderTraverse(a->lchild); 29 printf("%c ", a->ch); 30 PreOrderTraverse(a->rchild); 31 } 32 void PostOrderTraverse(BN* a)//后序遍历 33 { 34 if (a == NULL) 35 { 36 return; 37 } 38 PreOrderTraverse(a->lchild); 39 PreOrderTraverse(a->rchild); 40 printf("%c ", a->ch); 41 42 } 43 void test03() 44 { 45 BN nodeA = {'A',NULL,NULL }; 46 BN nodeB = { 'B',NULL,NULL }; 47 BN nodeC = { 'C',NULL,NULL }; 48 BN nodeD = { 'D',NULL,NULL }; 49 BN nodeE = { 'E',NULL,NULL }; 50 BN nodeF = { 'F',NULL,NULL }; 51 BN nodeG = { 'G',NULL,NULL }; 52 BN nodeH = { 'H',NULL,NULL }; 53 54 nodeA.lchild = &nodeB; 55 nodeA.rchild = &nodeF; 56 nodeB.rchild = &nodeC; 57 nodeC.lchild = &nodeD; 58 nodeC.rchild = &nodeE; 59 nodeF.rchild = &nodeG; 60 nodeG.lchild = &nodeH; 61 PreOrderTraverse(&nodeA); 62 cout << endl; 63 MisOrderTraverse(&nodeA); 64 cout << endl; 65 PostOrderTraverse(&nodeA); 66 cout << endl; 67 } 68 int main() 69 { 70 test03(); 71 return 0; 72 }