一、二叉树

1. 二叉树的顺序存储

#include<stdio.h>
#define MaxSize 10
struct TreeNode
{ElemType value; //结点中的数据元素bool isEmpty;   //结点是否为空
};//定义一个长度为MaxSize的数组t,按照从上到下、
//从左到右的顺序依次存储完全二叉树中的各个结点
TreeNode t[MaxSize];//二叉树顺序存储,根节点从1开始编号
//i的左孩子---2i
//i的右孩子---2i+1
//i的父节点---i/2向下取整//初始化时所有结点标记为空
for(int i=0;i<MaxSize;i++)
{t[i].isEmpty=true;
}

2. 二叉树的链式存储

//二叉树的结点(链式存储)--二叉链表
struct ElemType
{int value;
};typedef struct BiTNode
{ELemType data;                   //数据域struct BiTNode *lchild, *rchild; //左右孩子指针
} BiTNode, *BiTree;//n个结点的二叉链表共有n+1个空链域
//n个结点,一共有2n个指针,
//除了根结点,每个结点的头上都有一个天线,共有n-1个指针非空
//2n-(n-1)==n+1个空链域//定义一颗空树
BiTree root = NULL;//插入根结点1
root = (BiTree)malloc(sizeof(BiTNode));
root->data = {1};
root->lchild = NULL;
root->rchild = NULL;//插入新结点2
BiTNode *p2 = (BiTNode *)malloc(sizeof(BiTNode));
p2->data = {2};
p2->lchild = NULL;
p2->rchild = NULL;
root->lchild = p2; //作为根节点1的左孩子//插入新结点3
BiTNode *p3 = (BiTNode *)malloc(sizeof(BiTNode));
p3->data = {3};
p3->lchild = NULL;
p3->rchild = NULL;
root->rchild = p3; //作为根节点1的右孩子//插入新结点4
BiTNode *p4 = (BiTNode *)malloc(sizeof(BiTNode));
p4->data = {4};
p4->lchild = NULL;
p4->rchild = NULL;
p2->rchild = p4; //作为节点2的右孩子//插入新结点6
BiTNode *p6 = (BiTNode *)malloc(sizeof(BiTNode));
p6->data = {6};
p6->lchild = NULL;
p6->rchild = NULL;
p3->lchild = p6; //作为节点3的左孩子//插入新结点7
BiTNode *p7 = (BiTNode *)malloc(sizeof(BiTNode));
p7->data = {7};
p7->lchild = NULL;
p7->rchild = NULL;
p3->rchild = p7; //作为节点3的右孩子//插入新结点11
BiTNode *p11 = (BiTNode *)malloc(sizeof(BiTNode));
p11->data = {11};
p11->lchild = NULL;
p11->rchild = NULL;
p4->rchild = p11 //作为节点4的右孩子//插入新结点12
BiTNode *p12 = (BiTNode *)malloc(sizeof(BiTNode));
p12->data = {12};
p12->lchild = NULL;
p12->rchild = NULL;
p6->lchild = p12; //作为节点6的左孩子

3. 二叉树的链式存储——三叉链表

//二叉树的结点(链式存储)--二叉链表
struct ElemType
{int value;
};
//二叉树的结点(链式存储)--三叉链表
typedef struct BiTNode
{ELemType data;                  //数据域struct BiTNode *lchild,*rchild; //左右孩子指针struct BiTNode *parent;         //父结点指针
}BiTNode,*BiTree;//定义一颗空树
BiTree root = NULL;//插入根结点1
root = (BiTree)malloc(sizeof(BiTNode));
root->data={1};
root->lchild=NULL;
root->rchild=NULL;//插入新结点2
BiTNode *p2 = (BiTNode *)malloc(sizeof(BiTNode));
p2->data={2};
p2->lchild=NULL;
p2->rchild=NULL;
root->lchild=p2; //作为根节点1的左孩子//插入新结点3
BiTNode *p3 = (BiTNode *)malloc(sizeof(BiTNode));
p3->data={3};
p3->lchild=NULL;
p3->rchild=NULL;
root->rchild=p3; //作为根节点1的右孩子//插入新结点4
BiTNode *p4 = (BiTNode *)malloc(sizeof(BiTNode));
p4->data={4};
p4->lchild=NULL;
p4->rchild=NULL;
p2->rchild=p4; //作为节点2的右孩子//插入新结点6
BiTNode *p6 = (BiTNode *)malloc(sizeof(BiTNode));
p6->data={6};
p6->lchild=NULL;
p6->rchild=NULL;
p3->lchild=p6; //作为节点3的左孩子//插入新结点7
BiTNode *p7 = (BiTNode *)malloc(sizeof(BiTNode));
p7->data={7};
p7->lchild=NULL;
p7->rchild=NULL;
p3->rchild=p7; //作为节点3的右孩子//插入新结点11
BiTNode *p11 = (BiTNode *)malloc(sizeof(BiTNode));
p11->data={11};
p11->lchild=NULL;
p11->rchild=NULL;
p4->rchild=p11  //作为节点4的右孩子//插入新结点12
BiTNode *p12 = (BiTNode *)malloc(sizeof(BiTNode));
p12->data={12};
p12->lchild=NULL;
p12->rchild=NULL;
p6->lchild=p12; //作为节点6的左孩子

4. 二叉树的遍历

typedef struct BiTNode
{int data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//访问节点
void visit(BiTNode *)
{printf("%d\t",T->data);
}//先序遍历(根左右)
void PreOrder(BiTree T)
{if(T!=NULL){visit(T);               //访问根节点PreOrder(T->lchild);    //递归遍历左子树PreOrder(T->rchild);    //递归遍历右子树}
}//中序遍历(左根右)
void InOrder(BiTree T)
{if(T!=NULL){InOrder(T->lchild);    //递归遍历左子树visit(T);              //访问根节点InOrder(T->rchild);    //递归遍历右子树}
}//后序遍历(左右根)
void PostOrder(BiTree T)
{if(T!=NULL){PostOrder(T->lchild);   //递归遍历左子树PostOrder(T->rchild);   //递归遍历右子树visit(T);               //访问根节点}
}

5. 求树的深度

//求树的深度
int treeDepth(BiTree T)
{if(T==NULL){return 0;}    else{int l=treeDepth(T->lchild);int r=treeDepth(T->rchild);//数的深度=Max(左子树深度,右子树深度)+1return l>r? l+1: r+1;}
}

6. 二叉树的层次遍历

算法思想:
①初始化一个辅助队列
②根节点入队
③若队列非空,则队头节点入队,访问该结点,并将其左右孩子插入队尾(如果有的话)
④重复③直至队列为空
//二叉树的结点(链式存储)
typedef struct BiTNode
{char data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//链式队列结点
typedef struct LinkNode
{BiTNode *data;struct LinkNode *next;
}LinkNode;typedef struct
{LinkNode *front,*rear;  //队头队尾指针
}LinkQueue;//层序遍历
void LevelOrder(BiTree T)
{LinkQueue Q;InitQueue(Q);   //初始化辅助队列BiTree p;  EnQueue(Q,T);   //根结点入队while(isEmpty(Q)!=true)     //队列不空则循环{DeQueue(Q,p);   //队头节点出队visit(p);       //访问出队结点if(p->lchild!=NULL)EnQueue(Q,p->lchild);   //左孩子入队if(p->rchild!=NULL)EnQueue(Q,p->rchild);   //右孩子入队}
}

二、线索二叉树

1. 存储和遍历算法

//二叉树的结点(链式存储)
typedef struct BiTNode
{ElemType data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//线索二叉树结点(链式存储)
typedef struct ThreadNode
{ElemType data;struct ThreadNode *lchild,*rchild;int ltag,rtag;      //左、右线索标志//tag==0,指针指向孩子//tag==1,指针指向"线索"
}//中序遍历
void InOrder(BiTree T)  //改名findPre
{if(T!=NULL){InOrder(T->lchild);     //递归遍历左子树visit(T);               //访问根节点InOrder(T->rchild);     //递归遍历右子树}
}//访问结点
void visit(BiTNode *q)
{if(q==p)    //当前访问结点刚好是结点pfinal = pre;    //找到p的前驱elsepre=q;  //pre指向当前访问的节点
}//辅助全局变量,用于查找结点p的前驱
BiTNode *p;             //p指向目标结点
BiTNode *pre = NULL;    //指向当前访问结点的中序索引前驱
BiTNode *final = NULL;  //用于记录最终结果

2. 中序线索化二叉树

//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左、右线索标志
}ThreadNode,*ThreadTree;//全局遍历pre,指向当前访问结点的前驱
ThreadNode *pre = NULL;//中序线索化二叉树T
void CreatInThread(ThreadTree T)
{pre = NULL;     //pre初始为NULLif(T!=NULL)     //非空二叉树才能线索化{InThread(T);    //中序线索化二叉树Tif(pre->rchild==NULL)pre->rtag=1; //处理遍历的最后一个结点}
}//中序遍历二叉树,一边遍历一边线索化
void InThread(ThreadTree T)
{if(T!=NULL){InThread(T->lchild);    //中序遍历左子树visit(T);               //访问根节点InThread(T->rchild);    //中序遍历右子树}
}void visit(ThreadNode *q)
{if(q->lchild==NULL) //左子树为空,建立前驱线索{q->lchild=pre;q->ltag=1;}if(pre!=NULL && pre->rchild==NULL){pre->rchild=q;  //建立前驱结点的后继线索pre->rtag=1;    }pre=q;
}

3. 先序线索化二叉树

#include<stdio.h>
//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左右线索标志
}ThreadNode,*ThreadTree;//全局变量pre,指向当前访问结点的前驱
ThreadNode *pre = NULL;//先序线索化二叉树T
void CreatPreThread(ThreadTree T)
{pre = NULL;         //pre初始化为NULLif(T!=NULL)         //非空二叉树才能线索化{PreThread(T);   //先序线索化二叉树if(pre->rchild==NULL)pre->rtag=1; //处理遍历后的最后一个结点}
}//先序遍历二叉树,一边遍历一边线索化
void PreThread(ThreadTree T)
{if(T!=NULL){visit(T);                //先处理根节点if(T->ltag==0)  //lchild不是前驱线索时才线索化PreThread(T->lchild);    //先序遍历左子树PreThread(T->rchild);    //先序遍历右子树}
}void visit(ThreadNode *q)       //访问结点
{if(q->lchild==NULL) //左子树为空,建立前驱线索{q->lchild=pre;q->ltag=1;}if(pre!=NULL && pre->rchild==NULL){pre->rchild=q;  //建立前驱结点的后继线索pre->rtag=1;}pre=q;
}

4. 后续线索化二叉树

#include<stdio.h>
//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左右线索标志
}ThreadNode,*ThreadTree;//全局变量pre,指向当前访问结点的前驱
ThreadNode *pre = NULL;//后序线索化二叉树T
void CreatPosthread(ThreadTree T)
{pre = NULL;         //pre初始化为NULLif(T!=NULL)         //非空二叉树才能线索化{PostThread(T);   //后序线索化二叉树if(pre->rchild==NULL)pre->rtag=1; //处理遍历后的最后一个结点}
}//后序遍历二叉树,一边遍历一边线索化
void PostThread(ThreadTree T)
{if(T!=NULL){PreThread(T->lchild);    //后序遍历左子树PreThread(T->rchild);    //后序遍历右子树visit(T);                //访问根节点}
}void visit(ThreadNode *q)       //访问结点
{if(q->lchild==NULL) //左子树为空,建立前驱线索{q->lchild=pre;q->ltag=1;}if(pre!=NULL && pre->rchild==NULL){pre->rchild=q;  //建立前驱结点的后继线索pre->rtag=1;}pre=q;
}

5. 中序线索二叉树找中序后继

#include<stdio.h>
//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左右线索标志
}ThreadNode,*ThreadTree;//找到以P为根的子树中,第一个被中序遍历的结点
ThreadNode *FirstNode(ThreadNode *p)
{//循环找到最左下结点(不一定是叶节点)while(p->ltag==0)p=p->rchild;return p;
}//在中序线索二叉树中找到结点P的后继结点
ThreadNode *NextNode(ThreadNode *p)
{//右子树中最左下结点if(p->rtag==0)return FirstNode(p->rchild);elsereturn p->rchild;   //rtag==1直接返回后继线索
}//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法)
void InOrder(ThreadNode *T)
{for(ThreadNode *p = FirstNode(T);p!=NULL;p=NextNode(p))visit(p);
}

6. 中序线索二叉树找中序前驱

#include<stdio.h>
//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左右线索标志
}ThreadNode,*ThreadTree;//在中序线索二叉树中找到指定结点*p的中序前驱pre
//1.若p->ltag==1,则pre=p->lchild
//2.若p->ltag==0,找到左子树中,最后一个被中序遍历的结点 //找到以P为根的子树中,最后一个被中序遍历的结点
ThreadNode *LastNode(ThreadNode *p)
{//循环找到最右下结点(不一定是叶节点)while(p->rtag==0)p=p->rchild;return p;
}//在中序线索二叉树中找到结点p的前驱结点
ThreadNode *PreNode(ThreadNode *p)
{//左子树中最右下结点if(p->ltag==0)return LastNode(p->lchild);elsereturn p->lchild;
}//对中序线索二叉树进行逆向中序遍历
void RevInOrder(ThreadNode *T)
{for(ThreadNode *p=LastNode(T);p!=NULL;p=PreNode(p))visit(p);
}

7. 先序线索二叉树找先序后继

#include<stdio.h>
//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左右线索标志
}ThreadNode,*ThreadTree;//在先序线索二叉树中找到指定结点*p的先序后继next
//若p->rtag==1,则next=p->rchild
//若p->rtag==0:肯定有右孩子
//    1.有左孩子:根 左(根 左 右) 右 先序后继则为左孩子
//    2.没有左孩子: 根 右(根 左 右)  先序后继则为右孩子
ThreadNode *NextNode(ThreadNode *p)
{if(p->rtag==1)return p->rchild;else{if(p->ltag==0)          //有左孩子:根 左(根 左 右) 右 先序后继则为左孩子return p->lchild;else                    //没有左孩子: 根 右(根 左 右)  先序后继则为右孩子return p->rchild;}}

7. 先序线索二叉树找先序前驱

先序遍历中,左右子树中的结点只可能是根的后继,不可能是前驱.

//除非从头开始先序遍历

#include<stdio.h>
//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左右线索标志
}ThreadNode,*ThreadTree;//在先序线索二叉树中找到指定结点*p的先序前驱pre
//若p->ltag==1,则Pre=p->lchild
//若p->ltag==0:肯定有左孩子

8. 后序线索二叉树找后序前驱

在后序线索二叉树中找到指定结点*p的后续前驱Pre

若p->ltag==1,则Pre=p->lchild

若p->ltag==0:肯定有左孩子

1.有右孩子:左 右(左 右 根) 根 后续前驱Pre则为右孩子

2.没有右孩子:左(左 右 根) 根 后序前驱Pre则为左孩子

#include<stdio.h>
//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左右线索标志
}ThreadNode,*ThreadTree;ThreadNode *NextNode(ThreadNode *p)
{if(p->rtag==1)return p->rchild;else{if(p->ltag==0)          //有左孩子:根 左(根 左 右) 右 先序后继则为左孩子return p->lchild;else                    //没有左孩子: 根 右(根 左 右)  先序后继则为右孩子return p->rchild;}}

9. 后序线索二叉树找后序后继

在后序线索二叉树中找到指定结点*p的后续后继next

若p->rtag==1,则next=p->rchild

若p->rtag==0:肯定有右孩子

后续遍历中,左右子树中的结点只可能是根的前驱,不可能是后继

除非用后续遍历

#include<stdio.h>
//线索二叉树结点
typedef struct ThreadNode
{char data;struct ThreadNode *lchild,*rchild;int ltag,rtag;  //左右线索标志
}ThreadNode,*ThreadTree;

三、树的表示法

1. 双亲表示法(顺序存储)

#include<stdio.h>
#define Max_Tree_Size 100   //树中最多节点数
typedef struct PTNode   //树的结点定义
{               char data;          //数据元素int parent;         //双亲位置域
}PTNode;
typedef struct PTree    //树的类型定义
{PTNode nodes [Max_Tree_Size];   //双亲表示int n;              //结点数
}PTree;

2. 孩子表示法

#include<stdio.h>
#define Max_Tree_Size 100   //树中最多节点数
typedef struct CTNode
{int child;      //孩子结点在数组中的位置struct CTNode *next;    //下一个孩子
}CTNode;
typedef struct CTBox
{char data;struct CTNode *firstNode;   //第一个孩子
}CTBox;typedef struct CTree
{CTBox nodes[Max_Tree_Size];int n,r;    //结点数和根的位置
}CTree;

3. 孩子兄弟表示法

//二叉树的结点(链式存储)
typedef struct BiTNode
{char data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//树的存储--孩子兄弟表示法
typedef struct CSNode
{char data;struct CSNode *firstchild,*nextsibling; //第一个孩子和右兄弟指针
}CSNode,*CSTree;

四、树的遍历

1. 树的先根遍历

树的先根遍历

若树非空,先访问根结点

再依次对每棵子树进行先根遍历

//树的先根遍历 (深度优先遍历)
void PreOrder(TreeNode *R)
{if(R!=NULL){visit(R);   //访问根结点while(R还有下一个子树T){PreOrder(T);    //先根遍历下一棵子树}}
}
//树的先根遍历序列与这棵树相对应的二叉树的先序序列相同。

2. 树的后根遍历.

//若树非空,依次对每棵子树进行后根遍历,最后再访问根结点
void PostOrder(TreeNode *R)
{if(R!=NULL){while(R还有下一个子树T){PostOrder(T);   //后根遍历下一棵子树visit(R);       //访问根结点}}
}
//树的后根遍历序列与这棵树相对应的二叉树的中序序列相同。

五、森林的遍历

先序遍历森林和依次对各个树进行先根遍历效果相同。

先序遍历森林效果等同于依次对二叉树的先序遍历。

森林的中序遍历,效果上等同于依次对各个树进行后根遍历。

中序遍历森林的效果等同于依次对二叉树的中序遍历

树 森林 二叉树

先根遍历 先序遍历 先序遍历

后根遍历 中序遍历 中序遍历

六、二叉排序树

左子树结点值 < 根节点值 < 右子树结点值

进行中序遍历,可以得到一个递增的有序序列

1. 存储

//二叉排序树结点
typedef struct BSTNode
{int key;struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;

2. 在二叉排序树中查找值为key的结点(非递归)

BSTNode *BST_Search(BSTree T,int key)
{while(T!=NULL && key!=T->key)   //若树空或等于根节点值,则结束循环{if(key<T->key)      //小于,则在左子树上查找T=T->lchild;    elseT=T->rchild;    //大于,则在右子树上查找}return T;
}

3. 在二叉排序树中查找值为key的结点(递归)

BSTNode *BST_Search(BSTree T,int key)
{if(T==NULL)return NULL;    //空树,查找失败if(key==T->key)return T;else if(key<T->key)return BST_Search(T->lchild,key);   //左子树中查找else   return BST_Search(T->rchild,key);   //右子树中查找
}

4. 二叉排序树的插入和删除

//二叉排序树结点
typedef struct BSTNode
{int key;struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;

插入思想:

若原二叉排序树为空,则直接插入结点;否则,若关键字k小于根节点值,则插入到左子树,若关键字k大于根节点值,则插入到右子树。

在二叉排序树插入关键字为k的新结点(递归实现),空间复杂度:O(h)

int BST_Insert(BSTree &T,int k)
{if(T==NULL)         //原树为空,新插入的结点为根节点{T=(BSTree)malloc(sizeof(BSTNode));T->key=k;T->lchild=T->rchild=NULL;return 1;       //返回1,插入成功!}else if(k==T->key)  //树中存在相同关键字的结点,插入失败return 0;else if(k<T->key)   //插入到左子树return BST_Insert(T->lchild,k);else                //插入到右子树return BST_Insert(T->rchild,k);
}

按照str[]中的关键字序列建立二叉排序树

void Creat_BST(BSTree &T,int str[],int n)
{T=NULL;     //初始时T为空树int i=0;while(i<n)  //依次将每个关键字插入到二叉排序树中{BST_Insert(T,str[i]);i++;}
}

二叉排序树的删除:

先找到目标结点:
1.若被删除节点z是叶节点,则直接删除,不会破坏二叉排序树的性质.
2.若结点z只有一颗左子树或右子树,则让z的子树成为z父节点的子树,替代z的位置.
3.若结点z有左、右两颗子树,则令z的直接后继(或直接前驱)替代z,然后从二叉排序树中删去这个直接后继(或直接前驱),这样就转换成了第一或第二种情况.
左子树结点值 < 根结点值 < 右子树结点值
中序遍历可以得到一个递增的有序序列
z的后继:z的右子树中最左下结点(该节点一定没有左子树)
z的前驱:z的左子树中最右下结点(该节点一定没有右子树)

七、平衡二叉树

平衡二叉树(Balanced Binary Tree),检测平衡数(AVL)树----树上任一结点的左子树和右子树的高度之差不超过1.

结点的平衡因子=左子树高-右子树高

平衡二叉树结点的平衡因子的值只可能是-1,0,1

只要有任意节点的平衡因子绝对值大于1,就不是平衡二叉树

//平衡二叉树结点

#include<stdio.h>
typedef struct AVLNode
{int key;        //数据域int balance;    //平衡因子struct AVLNode *lchild,*rchild;
}AVLNode,*AVLTree;

1. LL—在A的左孩子的左子树中插入导致不平衡

LL平衡旋转(右单旋转)。
由于在结点A的左孩子(L)的左子树(L)上插入了新结点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要一次向右的旋转操作。将A的左孩子B向右上旋转代替A成为根节点,将A结点向右下旋转成为B的右子树的根节点,而B原右子树则作为A结点左子树。
代码思路:指针指向:f->A,p->B,gf->lchild/rchild=A;实现f向右下旋转,p向右上旋转:其中,f是爹,p为左孩子,gf是f他爹1.f->lchild=p->rchild;2.p->rchild=f;3.gf.lchild/rchild=p;

2. RR—在A的右孩子的右子树中插入导致不平衡

RR平衡旋转(左单旋转)。
由于在结点A的右孩子®的右子树®上插入了新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要一次向左的旋转操作。将A的右孩子B向左上旋转代替A成为根节点,将A结点向左下旋转成为B的左子树的根节点,而B的原左子树则作为A结点的右子树。
代码思路:指针指向:f->A,p->B,gf->lchild/rchild=A;实现f向左下旋转,p向左上旋转:其中,f是爹,p为左孩子,gf是f他爹1.f->rchild=p->lchild;2.p->lchild=f;3.gf.lchild/rchild=p;

3. LR—在A的左孩子的右子树中插入导致不平衡

LR平衡旋转(先左旋,再右旋)
由于在A的左孩子(L)的右子树(R)上插入新结点,A的平衡因子由1增至2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先左旋后右旋,先将A结点的左孩子B的右子树的根结点C向左上旋转提升到B结点的位置,然后再把该C结点向右上旋转提升到A结点的位置。

4. RL—在A的右孩子的左子树中插入导致不平衡

LR平衡旋转(先右旋,再左旋)
由于在A的右孩子®的左子树(L)上插入新结点,A的平衡因子由-1减至-2,导致以A为根的子树失去平衡,需要进行两次旋转操作,先右旋后左旋。先将A结点的右孩子B的左子树的根结点C向右上旋转提升到B结点的位置,然后再把该C结点向左上旋转提升到A结点的位置。

数据结构复习(五)——树和二叉树相关推荐

  1. 【数据结构】_树与二叉树

    目录 引言 一.什么是树? 1.树的定义 2.树的特点 3.树的表示法 二.树的一些基本术语 三.树的性质 四.什么是二叉树? 1.基本概念 2.二叉树的五种基本形态 3.二叉树的性质 五.满二叉树. ...

  2. 数据结构与算法——树和二叉树***

    第五章 :树和二叉树 树和图是两种重要的非线性结构.线性结构中结点具有唯一前驱和唯一后继的关系,而非线性结构中结点之间的关系不再具有这种唯一性.其中,树形结构中结点间的关系是前驱唯一而后继不唯一,即元 ...

  3. Python__数据结构与算法——树、二叉树(实现先、中、后序遍历)

    目录 一.树 二.二叉树 树和前面所讲的表.堆栈和队列等这些线性数据结构不同,树不是线性的.在处理较多数据时,使用线性结构较慢,而使用树结构则可以提高处理速度.不过,相对于线性的表.堆栈和队列等线性数 ...

  4. 数据结构实验二 树和二叉树的实现

    广州大学学生实验报告 开课实验室:计算机科学与工程实验(电子楼418A)     2019年5月13日 学院 计算机科学与教育软件学院 年级.专业.班 计算机科学与技术172班 姓名 学号 17061 ...

  5. 【数据结构Note5】- 树和二叉树(知识点超细大全-涵盖常见算法 排序二叉树 线索二叉树 平衡二叉树 哈夫曼树)

    文章目录 5.1 树和二叉树引入 5.1.1 树的概念 5.1.2 树的表示 5.1.3 树中基本术语 5.2 二叉树 5.2.1 概念 5.2.2 二叉树的性质 5.2.3 特殊的二叉树 5.2.4 ...

  6. 【数据结构_Day05】 树和二叉树、树和森林、哈夫曼树

    1.树 根节点:非空树中无前驱结点的结点 结点的度:结点拥有的子树数 树的度:树内各结点的度的最大值 森林不一定是树,树一定是森林 2.二叉树 二叉树和树是不一样的概念 二叉树严格区分左子树和右子树, ...

  7. 数据结构-实验二  树和二叉树的实现

     广州大学学生实验报告 开课实验室:计算机科学与工程实验(电子楼417)     2018年05月16日 学院 计算机科学与教育软件学院 年级.专业.班 网络161 姓名 卟咚君 学号 1606100 ...

  8. 数据结构知识点总结-树、二叉树、二叉树遍历、满二叉树、完全二叉树、查找二叉树、平衡二叉树、红黑树、B树、B+树

    树 在计算器科学中,树(英语:tree)是一种抽象数据类型或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合.它是由n(n>0)个有限节点组成一个具有层次关系的集合.把它叫做 ...

  9. 数据结构与算法——树与二叉树详细分享

    一.树 1.定义:由n个有限节点组成一个具有层次关系的集合,看起来像一颗倒挂的树,特点: 2.特点: a.每个节点有0个或多个子节点 b.没有父节点的节点称为根节点(A) c.每一个非根节点有且只有一 ...

  10. 数据结构与算法 | 树与二叉树

    树的概念 二叉树的概念 树的概念和结构 树是一种非线性的数据结构,它是由n个有限结点组成一个具有层次关系的集合,把它叫做树是因为它看起来像一棵倒挂的树,如图所示 有一个特殊的结点,称为根节点,根节点没 ...

最新文章

  1. 什么是动态DNS 动态DNS有什么用
  2. PIX 525下的怪问题(需在防火墙后的同子网上激活之后才能在INTERNET上使用)?...
  3. SQL Server Integration Services 包的开发与部署初探
  4. Big Data應用:以玩家意見之數據分析來探討何謂健康型線上遊戲(上)
  5. unbalanced enable irq 问题的解决 以及共享的gpio中断引起的问题
  6. 河南上oracle客户,解决Oracle监听服务报错
  7. Spring5(3)---Spring5概述
  8. spark中local模式与cluster模式使用场景_Spark内核及通信框架概述-针对面试(后面有源码分析)...
  9. 敏捷开发般若敏捷系列之八:敏捷的未来会怎样?
  10. ps快捷键大全(表格汇总)
  11. vue-draggle实现元素拖动,放大,缩小,多元素一起改变位置
  12. OSChina 周三乱弹 ——程序员是将咖啡转变成代码的工具
  13. Babylonjs 官网demo预览图合集整理 带说明
  14. rundll32.exe传入参数
  15. Unity shader 实现圆角矩形
  16. 什么从什么写短句_照样子写句子.(写清“谁或什么 “在什么地方 “做什么或怎么样 ) 例1:小朋友在河边种树. 例2:麻雀在窝里睡着了. 题目和参考答案——青夏教育精英家教网——...
  17. [精华] nucleus实时操作系统MTK手机软件系统工程和配置简介
  18. 磁感应强度、磁场强度、磁动势之三者间的关系
  19. 【计算机网络】网络层:路由器的构成
  20. 外部表不是预期的格式-excel

热门文章

  1. android开发:Theme.Light.NoTitleBar和Theme.Light.NoTitleBar.Fullscreen的区别
  2. 2021 AAAI best Paper - Informer-2020 学习记录
  3. matlab实现ica,Matlab用ICA进行话语分离
  4. 求大神赐教Maven中子模块之间无法建立依赖关系问题
  5. 笔记本进入pe却看不到计算机硬盘,11代cpu笔记本进pe看不到硬盘解决方法(PE完美解决)...
  6. python2和python3一些不同
  7. 微信开发者工具 网络连接失败
  8. Windows音频录制软件哪个好
  9. 关于HTTP协议之谈网址URL劫持的影响
  10. 饥荒机器人怎么解锁_饥荒机器人怎么玩 饥荒机器人详细玩法