数据结构——普通二叉树

  1. 普通二叉树

关于二叉树的深度和高度涉及到结点的层数,有的教材规定根结点在第0层,有的则规定根结点在第1层。

 以《数据结构-C语言版》(严蔚敏,吴伟民版)的为准:高度和深度是同一个概念,根节点在第1层,树的高度是看一共有几层。 高度为h的完全二叉树,最多有2^n-1个节点,第k层最多有2^(k-1)个节点。 含有n个节点的完全二叉树,高度为(logn + 1)下取整。

对于完全二叉树:

如果第一个元素下标为1,则第k个元素的左孩子为2*k,右孩子为2*k+1,父节点为 k / 2 下取整,最后一个父节点为 length / 2 下取整。

如果第一个元素下标为0,则第k个元素的左孩子为2*k+1,右孩子为2*k+2,父节点为 (k - 1)/ 2 下取整,最后一个父节点为 length / 2 下取整 - 1。

二叉树的前驱后继节点,表示中序遍历时,一个节点的前一个和后一个。

高度为h的完全二叉树,最多有2^h-1个节点。

节点为n的完全二叉树,高度为logn。(高度为0的树有1个结点)。

  • 1.2 二叉树的遍历

二叉树的有三种遍历方式,先中后序遍历,“先、中、后”表示根节点的遍历时间。

先序:先遍历分支的根节点,再遍历左子树,最后遍历右子树。

先序序列:ABDFECGHI

中序:先遍历分支的左子树,再遍历根节点,最后遍历右子树。

中序序列:DBEFAGHCI

 

后序:先遍历分支的左子树,再遍历右子树,最后遍历根节点。

后序序列:DEFBHGICA

  

  通过包含中序序列(通过前后序列创建出的二叉树不唯一)的两个序列推出 剩余的一个序列,算法分别用前中推后,中后推前。

typedef struct BinaryTreeNode
{
    ElemType data;
    struct BinaryTreeNode *Left;
    struct BinaryTreeNode *Right;
}*BinaryTree;

void PreAndInToPost(ElemType* pre, ElemType* in,int length) {                
    if (length == 0) return;
    int rootIndex;
    BinaryTree BT = new BinaryTreeNode;
    BT->data = *pre;
    for (rootIndex = 0; in[rootIndex] != *pre; rootIndex++);
    PreAndInToPost(pre + 1, in, rootIndex);
    PreAndInToPost(pre + rootIndex + 1, in + rootIndex + 1, length - (rootIndex + 1));
    cout << BT->data << " ";
}

void PostAndInToPre(ElemType* in, ElemType* post,int length) {
    if (length == 0) return;
    int rootIndex;
    BinaryTree BT = new BinaryTreeNode;
    BT->data = *(post + length - 1);
    for (rootIndex = length - 1; in[rootIndex] != *(post + length - 1); rootIndex--);
    cout << BT->data << " ";
    PostAndInToPre(in, post, rootIndex);
    PostAndInToPre(in + rootIndex + 1, post + rootIndex, length - (rootIndex + 1));
}
View Code

二叉树的三种遍历实现(递归+非递归):

后序遍历非递归,是借用两个栈A,B,用A栈访问,压栈顺序为中左右(先序为中右左),把这些节点再存到B栈里,最后一起出栈。

//先序
void preorderUnRecur(BTree T) {
    stack<BTree>s;
    s.push(T);
    while (!s.empty()) {
        T = s.top();
        s.pop();
        cout << T->data << " ";
        if (T->Right)
            s.push(T->Right);
        if (T->Left)
            s.push(T->Left);
    }
    cout << endl;
}

//中序
void inorderUnRecur(BTree T) {
    if (!T)return;
    stack<BTree>s;
        while (!s.empty() || T) {
            if (T) {
                s.push(T);
                T = T->Left;
            }
            else {
                T = s.top(); s.pop();
                cout << T->data << " ";
                T = T->Right;
            }
        }
    cout << endl;
}

//后序

void postorderUnRecur(BTree T) {
    if (!T)return;
    stack<BTree>s1,s2;
    s1.push(T);
        while (!s1.empty()) {
            T = s1.top(); s1.pop();
            s2.push(T);
            if (T->Left)s1.push(T->Left);
            if (T->Right)s1.push(T->Right);
    }
        while (!s2.empty()) {
            cout << s2.top()->data << " ";
            s2.pop();
        }
    cout << endl;
}

 

递归实现,相比来说就比较简单了:

void Inorder(BTree BT) {
    if (!BT)return;
    Inorder(BT->Left);
    cout << BT->data << " ";
    Inorder(BT->Right);
}
void Preorder(BTree BT) {
    if (!BT)return;
    cout << BT->data << " ";
    Preorder(BT->Left);
    Preorder(BT->Right);
}
void Postorder(BTree BT) {
    if (!BT)return;
    Postorder(BT->Left);
    Postorder(BT->Right);
    cout << BT->data << " ";
}
View Code
  • 1.3 二叉树的构建

  二叉树的建立一般有两种方法:

(1)用数组的方式,或者一个个输入,按照节点的顺序,用一个特殊值(比如0,# )表示当前位置没有节点。但这样总归是会出现冲突的,比如节点的值就是0, # 的ASCII值。就不做写了。

(2)给定包含中序序列的两个序列。以下为 给定前序、中序序列时,创建二叉树。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 typedef char ElemType;
 5 
 6 typedef struct BinaryTreeNode
 7 {
 8     ElemType data;
 9     struct BinaryTreeNode *Left;
10     struct BinaryTreeNode *Right;
11 }*BinaryTree;
12 
13 BinaryTree CreatBTFromPreAndIn(ElemType* pre, ElemType* in, int length) {
14     if (length == 0) return NULL;
15     int rootIndex;
16     BinaryTree BT = new BinaryTreeNode;
17     //将当前根节点入树
18     BT->data = *pre;
19     for (rootIndex = 0; in[rootIndex] != *pre; rootIndex++);    
20     BT->Left = CreatBTFromPreAndIn(pre+1, in,rootIndex);
21     BT->Right = CreatBTFromPreAndIn(pre+rootIndex+1, in+rootIndex+1,length-(rootIndex+1));
22     return BT;
23 }
24 BinaryTree CreatBTFromPostAndIn(ElemType* in, ElemType* post, int length) {
25     if (length == 0) return NULL;
26     int rootIndex;
27     BinaryTree BT = new BinaryTreeNode;
28     //将当前根节点入树
29     BT->data = *(post + length - 1);
30     for (rootIndex = length - 1; in[rootIndex] != *(post + length - 1); rootIndex--);
31     BT->Left = CreatBTFromPostAndIn(in, post, rootIndex);    
32     BT->Right = CreatBTFromPostAndIn(in + rootIndex + 1, post + rootIndex/*删掉post的最后一个*/, length - (rootIndex + 1));
33     
34     return BT;
35 }
36 
37 
38 void Inorder(BinaryTree BT) {
39     if (!BT)return;
40     Inorder(BT->Left);
41     cout << BT->data << " ";
42     Inorder(BT->Right);
43 }
44 void Preorder(BinaryTree BT) {
45     if (!BT)return;
46     cout << BT->data << " ";
47     Preorder(BT->Left);
48     Preorder(BT->Right);
49 }
50 void Postorder(BinaryTree BT) {
51     if (!BT)return;
52     Postorder(BT->Left);
53     Postorder(BT->Right);
54     cout << BT->data << " ";
55 }
56 
57 int main() {
58     char pre[] = "ABDGHCEIF";
59     char in[]  = "GDHBAEICF";
60     char post[]= "GHDBIEFCA";
61     BinaryTree BT1 = CreatBTFromPreAndIn(pre, in, strlen(in));
62     BinaryTree BT2 = CreatBTFromPostAndIn(in, post, strlen(in));
63     Postorder(BT1);
64     cout << endl;
65     Preorder(BT1);
66     cout << endl;
67     return 0;
68 }
View Code

前序、中序序列构建二叉树图解:

  

1.4关于二叉树的小算法

  •   二叉树的深度
int height(BinaryTree L) {
    if (L == NULL)
        return 0;
    int left = height(L->Left);
    int right = height(L->Right);
    return left >= right ? left + 1 : right + 1;
}
  •  小于O(n),给出完全二叉树的长度(就是不准遍历)

完全二叉树一般都是用数组存储的(而这个算法是改不成数组的),也都是通过计算找子树、父节点的,我觉得实际操作中这个意义不大。

主要是练习对完全二叉树的理解。

int nodeNum(Node head) {
    if (!head) return 0;
    bs(head, 1, mostLeftLevel(head, 1));
}
int bs(Node head, int level, int height) {
    if (!head) return 1;
    if (mostLeftLevel(head->right, level + 1) == height) {
        return 1 << (height - level) + bs(head->right, level + 1, height);
    }
    else {
        return 1 << (height - level - 1) + bs(head->left, level + 1, height);
    }
}
int mostLeftLevel(Node head, int level) {
    Node p = head;
    while (p->left) {
        p = p->left;
        level++;
    }
    return level;
}

 

转载于:https://www.cnblogs.com/czc1999/p/10279331.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值