二叉树
树的简单概念
-
没有父结点的结点为根结点
-
没有子结点的结点为叶结点
-
上层是下层的父结点
-
下层是上层的子结点
-
节点的度:一个节点含有多少个子节点
-
空树层数为0,层数从一开始数
-
由多颗不相交的树组成的叫森林
树的结构定义
//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的树( 每个结点最多只有两个子树)
特殊的二叉树
- 满二叉树:每一层节点都达到最大值
- 完全二叉树:前K-1层是满的,最后一层可以不满,必须是从左到右连续的
- 树-------》二叉树------》满二叉树------》完全二叉树
- 对于任何一颗二叉树,如果度为0其叶结点为n0,度为2的分支结点个数为n2,则有n0=n2+1
完全二叉树
- 父亲下表是i,左孩子下表i*2+1;右孩子下标为2 *i=2;
- 孩子是i,父亲是(i-1)/2
堆
堆就是完全二叉树
逻辑结构:完全二叉树
物理结构:数组
大堆
- 完全二叉树
- 每个父亲都大于等于孩子
- 堆顶就是最大值
小堆
- 完全二叉树
- 每个父亲都小于等于孩子
- 堆顶就是最小值
根不是最大的就是最小的,可以用来选数,排序(堆排序)
数据建堆:主要依赖向下调整算法
#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
- 变成小堆
- 选出最小的数
- 放最后,
- 在成小堆
- 选出次小的数
- 放到倒数第二位置
- …
链式二叉树
遍历:前序 中序 后序 层序
深度优先遍历:前序 中序 后序 (深度:先往深走,再往回退)
广度优先遍历:层序
任何一个二叉树都要看成三个部分
- 根节点
- 左子树
- 右子树
前序:(先根遍历)根 左子树 右子树
中序: 左子树 根 右子树
后序:左子树 右子树 根
层序:一层一层走
#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;
}
层序:广度优先
前中后序;深度优先
递归
- 子问题
- 返回条件(子问题不能再缩小)
二叉树
子问题:左子树 右子树
返回条件: 空树
#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;
}
建议:画一遍图