二叉树详解

二叉树

树的简单概念

  1. 没有父结点的结点为根结点

  2. 没有子结点的结点为叶结点

  3. 上层是下层的父结点

  4. 下层是上层的子结点

  5. 节点的度:一个节点含有多少个子节点

  6. 空树层数为0,层数从一开始数

  7. 由多颗不相交的树组成的叫森林

树的结构定义

//N为度 ,可能造成空间浪费
struct TreeNode
{
    int val;
    TreeNode* child[N]
}
struct TreeNode
{
	int val;
	TreeNodeSeqList childs;//c
    vector<TreeNode*>chiles;//c++
}
  • 左孩子-右兄弟
//左孩子-右兄弟
struct TreeNode
{
    int val;
    TreeNode*_leftChild;
    TreeNode*_rightBrother;
}
  • 数组表示

    存父亲的下标

    并查集就是这种结构森林

树是递归定义的

  • 任何一棵树都可以看作是由根和他的子树构成的
  • 定义结构和形态是相似的

树与非树

  • 树不能构成回路

二叉树

二叉树就是度为2的树( 每个结点最多只有两个子树)

特殊的二叉树

  1. 满二叉树:每一层节点都达到最大值
  2. 完全二叉树:前K-1层是满的,最后一层可以不满,必须是从左到右连续的
  3. 树-------》二叉树------》满二叉树------》完全二叉树
  • 对于任何一颗二叉树,如果度为0其叶结点为n0,度为2的分支结点个数为n2,则有n0=n2+1

完全二叉树

  • 父亲下表是i,左孩子下表i*2+1;右孩子下标为2 *i=2;
  • 孩子是i,父亲是(i-1)/2

堆就是完全二叉树

逻辑结构:完全二叉树

物理结构:数组

大堆

  1. 完全二叉树
  2. 每个父亲都大于等于孩子
  3. 堆顶就是最大值

小堆

  1. 完全二叉树
  2. 每个父亲都小于等于孩子
  3. 堆顶就是最小值

根不是最大的就是最小的,可以用来选数,排序(堆排序)

数据建堆:主要依赖向下调整算法

#include<stdlib.h>
#include<stdio.h>
typedef int HPDataType;
typedef struct Heap
{
    HPDataType* _a;
    int _size;
    int _capacity;
}Heap;
void Swap(HPDataType*p1,HPDatType*p2)
{
    HPDataType tem=*p1;
    *p1=*p2;
    *p2=tem;
}
//前提:左右子树都是小堆
void AdjustDown(HPData*a,int n,int root)
{
    //找出左右孩子中小的那一个
    int parent=root;
    int child = parent*2+1;
    while(child<n)
    {
        //找出小的孩子
        if(chid+1<n&&a[child+1]<a[child])
    	{
        	++child;
    	}
        //如孩子大于孩子交换
    	if(a[child]<a[parent])
    	{
        	Swap(&a[child],&a[parent]);
            parent=child;
            child=parents*+1;
    	}
        else
        {
            break;
        }
    }
    
}
void HeapInit(Heap* php,HPDataType* a,int n)
{
 	php->_a=(HPDataType*)malloc(sizeof(HPDataType)*n);
 	memcpy(php->_a,a,sizeof(HPDataType)*n);
 	php->_size=n;
 	php->_capacity=n;
 	
 	//构建堆 
    for(int i=(n-1-1)/2,i>=0;--i)
    {
        AdjustDown(php->_a,php->_size,i);
    }
}
void HeapDestory(Heap* php)
{
    assert(php);
    free(php->_a);
    php->_a=NULL;
    php->_capacity=php->_size=0;
}
void HeapPush(Heap* php,HPDataType x)
{
    assert(php);
    if(php->_size==php->_capacity)
    {
        php->_capacity*=2;
        HPDataType*tem=realloc(php->_a,sizeof(PDataType)*php->_capacity);
        php->_a=tem;
    }
    php->_a[php->sizeof++]=x;
    AdjustUp(php->_a,php->_size,php->_size-1);
}
void AdjustUp(HPData*a,int n,int child)
{
    int parent=(child-1)/2;
    while(child>0)
    {
        if(a[child]<a[parent])
        {
            Swap(&a[child],&a[parent]);
            child=parent;
            parent=(child-1)/2;
        }
        else
        {
            break;
        }
    }
}
void HeapPop(Heap* php)
{
    assert(php);
    assert(php->_size>0);
    Swap(&php->_a[0],&php->_a[php->_size-1]);
    php->_soze--;
    AdjustDown(php->_a,php->size,0);
}
HPDataType HeapTop()
{
    assert(php);
	return php->_a[0]
} 
int main()
{
	int a[]={27,15,19,18,28,34,65,49,25,37};
    Heap hp;
    HeapInit(hp,a,10);
	return 0;
} 

向下调整算法

void AdjustDown(int *a,int n,int root)
{
 int parent=root;
 int child=parent*2=1;
 while(child<n)
 {
     if(child+1<n&&a[child+1]<a[child])
     {
         ++child;
     }
     if(a[parent]>a[child])
     {
         int tem=a[parent];
         a[parent]=a[child];
         a[child]=tem;
         parent=child;
         child=parent*2+1;
     }
     else
     {
         break;
     }
 }
}

堆排序

void HeapSort(int *a,int n);
{
    //1.建堆
    //for(int i=(n-1-1)/2,i>=0;++i)
    //时间复杂度?
    //就假设树犹N个几点,树高度:log2N
    //要注意这里时间复杂度不是N*logN
    for(int i=n-1;i>=0;++i)
    {
        AdjustDown(a,n,i);
    }
    int end=n-1;
    while(end>0)
    {
        Swap(&a[0],&a[end]);
        //再继续选次小的树
        AdjustDown(a,end,0);
        --end;
    }
}
int main()
{
    int arr[]={27,15,19,18,28,34,65,49,25,37};
    
    return 0;
}

排降序:建小堆

排升序:建大堆

堆排序:时间复杂度N*logN

  1. 变成小堆
  2. 选出最小的数
  3. 放最后,
  4. 在成小堆
  5. 选出次小的数
  6. 放到倒数第二位置

链式二叉树

遍历:前序 中序 后序 层序

深度优先遍历:前序 中序 后序 (深度:先往深走,再往回退)

广度优先遍历:层序

任何一个二叉树都要看成三个部分

  1. 根节点
  2. 左子树
  3. 右子树

前序:(先根遍历)根 左子树 右子树

中序: 左子树 根 右子树

后序:左子树 右子树 根

层序:一层一层走

#include<stdio.h>
#include<stdilb.h>
typedef char BTDataType;
typedef struct BinaryTreeNode
{
    BTDataType _data;
    struct BinayTreeNode* _left;
    struct BinayTreeNode* _right;
}BTNode;
void PrevOrder(BTNode*root)
{
    if(root==NULL)
    {
        printf("NULL");
        return ;   
    }
    printf("%c",root->_data);
    PrevOrder(root->_left);
    PrevOrder(root->_right);
}
BTNode*CreateNode(int x)
{
    BTNode*node=(BTNode)malloc(sizeof(BTNode));
    node->_data=x;
    node->_left=NULL;
    node->_right=NULL;
    return node;
}
void TreeSize(BTNode*root,int* psize)
{
    if(root==NULL)
        return 0;
    else(*psize)++;
    TreeSize(root->_left,psize);
    TreeSize(root->_right,psize);
}
//或者
int TreeSize(BTData*root)
{
   if(root==NULL)
   {
       return 0;
   }
   else
   {
    	return 1+TreeSize(root->_left)+TreeSize(root->right);   
   }
}
int main()
{
    BTBode*A=CreateNode('A');
    BTBode*B=CreateNode('B');
    BTBode*C=CreateNode('C');
    BTBode*D=CreateNode('D');
    BTBode*E=CreateNode('E');
    A->_left=B;
    A->_right=C;
    B->_left=D;
    B->_left=E ;
    PrevOrder(A);
    return 0;
}

层序:广度优先

前中后序;深度优先

递归

  1. 子问题
  2. 返回条件(子问题不能再缩小)

二叉树

子问题:左子树 右子树

返回条件: 空树

#include<stdio.h>
#include<stdlib.h>
#inlcude<string.h>
void PrevOrder(BTNode*root)
{
    if(root==NULL)
    {
        printf("NULL");
        return;
    }
    printf("%c",root->_data);
    PrevOrder(root->_left);
    PrevOrdre(root->_right);
}
int main()
{
    return 0;
}

建议:画一遍图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值