二叉树总结

分大概几个部分吧,定义(包括平衡、完全、满二叉树),基本性质、存储方式、遍历方法,树转成二叉树方法五个部分,最后是代码。

一、定义

wiki上定义:In computer science, a binary tree is a tree data structure in which each node has at most two child nodes, usually distinguished as "left" and "right". Nodes with children are parent nodes, and child nodes may contain references to their parents.Binary trees are used to implement binary search trees and binary heaps.

对于高度的定义:wiki:The depth (or height) of a tree is the length of the path from the root to the deepest node in the tree. A (rooted) tree with only one node (the root) has a depth of zero.!!貌似中国的一般教科书和百度百科对于树的高度的定义和wiki上是不一样的(中国特色?):“树的最大层数为树的高度,根节点为第一层”,这种方法可以定义出空树的情况吧可能,下面都采用这种定义。

满二叉树:A full binary tree (sometimes proper binary tree or 2-tree or strictly binary tree) is a tree in which every node other than the leaves has two children. Sometimes a full tree is ambiguously defined as a perfect tree.

完全二叉树:A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible.

平衡二叉树:A balanced binary tree is commonly defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1, although in general it is a binary tree where no leaf is much farther away from the root than any other leaf.(它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树)

 

二、基本性质

1) 在二叉树中,第i层的结点总数不超过2^(i-1);   
2) 深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点;   
3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;   
4) 具有n个结点的完全二叉树的深度为int(log2n)+1

 

三、存储方式

存储的方式和图一样,有链表和数组两种,用数组存访问速度快,但插入、删除节点操作就比较费时了。实际中更多的是用链来表示二叉树的。

 

四、遍历方法

分为前序遍历,中序遍历和后序遍历,和按层次遍历。前三种方法可用递归实现,比较简单,不用递归的可以自己模拟栈操作来实现非递归的遍历方法。按层遍历也比较简单,就是自己实现一个队列就可以了,也可以用数组来模拟。需要注意的是后序遍历的非递归算法,需要一个标识来标识某个节点的状态,具体的就是当一个节点左孩子被遍历的时候为一个状态,当左右两个节点都被遍历的时候又是一个状态,只有一个节点的左右孩子几点都被遍历,才可以输出这个节点的值,这个和后序遍历的定义差不多。

 

五、树转换成二叉树

这个其实也不难分三步:连线、抹线、旋转三步就可以了。
1)连线:每一层兄弟结点连在一起。
2)抹线:对每个结点,除了其最左端的子女结点外,抹去与其余子女结点的分支连线。
3)以每个结点的做左端的子女结点为轴,顺时针转45度。

 

下面代码中的二叉树结构如图:

#include <iostream>
using namespace std;

typedef char TElemType;
const char INVALID = '^';//没有节点时候用^表示
const int MAX_NODE_COUNT = 20;
typedef struct BTreeNode
{
        TElemType m_data;
        struct BTreeNode *m_pLeft;
        struct BTreeNode *m_pRight;
}BTreeNode, *BTree;
//根据数组中的元素来构造链式二叉树
void createBTree(BTree &rt, char *values);

void preOrderBTree(const BTreeNode *rt);
void inOrderBTree(const BTreeNode *rt);
void postOrderBTree(const BTreeNode *rt);

void preOrderNoRe(BTreeNode *rt);
void inOrderNoRe(BTreeNode *rt);
void postOrderNoRe(BTreeNode *rt);

void levelTraverse(BTreeNode *rt);

int main()
{
        char values[] = {'A', 'B', 'C', '^', '^', '^', 'D', 'E', 'F', '^', '^', 'G', '^', '^', 'H', '^', 'I', '^', '^', '\0'};
        BTree rt = NULL;
        createBTree(rt, values);

        printf("preOrderBTree:\n");
        preOrderBTree(rt);
        printf("\npreOrderNoRe:\n");
        preOrderNoRe(rt);

        printf("\ninOrderBTree:\n");
        inOrderBTree(rt);
        printf("\ninOrderNoRe:\n");
        inOrderNoRe(rt);

        printf("\npostOrderBTree:\n");
        postOrderBTree(rt);
        printf("\npostOrderNoRe:\n");
        postOrderNoRe(rt);

        printf("\nlevelTraverse:\n");
        levelTraverse(rt);
        printf("\n");
        return 0;
}

/*
void createBTree(BTreeNode **rt, char *values)
{
        int static i=0;
        char value = values[i++];
        if(value == '\0')
                return;
        if(value == INVALID)
        {
                *rt = NULL;
                return;
        }
        *rt = (BTreeNode *)malloc(sizeof(BTreeNode));
        (*rt)->m_data = value;
        createBTree(&((*rt)->m_pLeft), values);
        createBTree(&((*rt)->m_pRight), values);
}
*/
//这个函数的声明很特别,指针的引用,可以简化代码,否则会像上面的一个样,看起来很乱
//如果不用typedef,那么也可以这样来声明指针的引用:void createBTree(BTreeNode *&rt, char *values)

void createBTree(BTree &rt, char *values)
{
        int static i=0;
        char value = values[i++];
        if(value == '\0')
                return;
        if(value == INVALID)
        {
                rt = NULL;
                return;
        }
        rt = (BTreeNode *)malloc(sizeof(BTreeNode));
        rt->m_data = value;
        createBTree(rt->m_pLeft, values);
        createBTree(rt->m_pRight, values);
}

void preOrderBTree(const BTreeNode *rt)
{
        if(rt)
        {
                printf("%c\t", rt->m_data);
                preOrderBTree(rt->m_pLeft);
                preOrderBTree(rt->m_pRight);
        }
}

void inOrderBTree(const BTreeNode *rt)
{
        if(rt)
        {
                inOrderBTree(rt->m_pLeft);
                printf("%c\t", rt->m_data);
                inOrderBTree(rt->m_pRight);
        }
}
void postOrderBTree(const BTreeNode *rt)
{
        if(rt)
        {
                postOrderBTree(rt->m_pLeft);
                postOrderBTree(rt->m_pRight);
                printf("%c\t", rt->m_data);
        }
}

void preOrderNoRe(BTreeNode *rt)
{
        BTreeNode *stack[MAX_NODE_COUNT] = {NULL};
        int top = -1;
        while(rt || top > -1)
        {
                if(rt)
                {
                        printf("%c\t", rt->m_data);
                        stack[++top] = rt;
                        rt = rt->m_pLeft;
                }
                else
                {
                        rt = stack[top--];
                        rt = rt->m_pRight;
                }
        }
}

void inOrderNoRe(BTreeNode *rt)
{
        BTreeNode *stack[MAX_NODE_COUNT] = {NULL};
        int top = -1;
        while(rt || top > -1)
        {
                if(rt)
                {
                        stack[++top] = rt;
                        rt = rt->m_pLeft;
                }
                else
                {
                        rt = stack[top--];
                        printf("%c\t", rt->m_data);
                        rt = rt->m_pRight;
                }
        }
}

void postOrderNoRe(BTreeNode *rt)
{
        BTreeNode *stack[MAX_NODE_COUNT] = {NULL};
        int stack_tag[MAX_NODE_COUNT] = {-1};
        int top = -1;

        while(rt || top > -1)
        {
                while(rt)
                {
                        stack[++top] = rt;
                        stack_tag[top] = 0;
                        rt = rt->m_pLeft;
                }
                if(top > -1)
                {
                        if(stack_tag[top] == 0)
                        {
                                rt = stack[top];
                                rt = rt->m_pRight;
                                stack_tag[top] = 1;
                        }
                        else
                        {
                                //这里不能是rt = stack[top--]; printf("", rt->m_data);如果这样写的话rt下次while循环时,rt的左孩子会又被加入到stack中,无限循环
                                printf("%c\t", stack[top--]->m_data);
                        }
                }
        }
}

void levelTraverse(BTreeNode *rt)
{
        BTreeNode *queue[MAX_NODE_COUNT] = {NULL};
        int front = 0;
        int rear = 0;
        BTreeNode *p = rt;
        if(p)
                queue[rear++] = p;

        while(front != rear)
        {
                p = queue[front++];
                printf("%c\t", p->m_data);
                if(p->m_pLeft)
                        queue[rear++] = p->m_pLeft;
                if(p->m_pRight)
                        queue[rear++] = p->m_pRight;
        }
}



 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值