二叉树和二叉搜索树的基础操作
#include
using namespace std;
#define OK 1
#define ERROR -1
#define OVERFLOW -2
typedef int Status;
typedef int BElemtype;
typedef struct BTNode
{
//数据,左子树,右子树,是否是是第一个,
BElemtype data;
struct BTNode *lchild;
struct BTNode *rchild;
struct BTNode *node;
bool isfirst;
}BTNode,*BiTree;
//创建一个树,以0为结束点
//以递归实现
Status Init_BiTree(BiTree &T)
{
BElemtype e;
cin>>e;
if(!e)
return OK;
T=(BiTree)malloc(sizeof(BTNode));
if(!T)
exit(OVERFLOW);
T->data=e;
T->lchild=NULL;
T->rchild=NULL;
Init_BiTree(T->lchild);
Init_BiTree(T->rchild);
return OK;
}
//求叶子结点的个数
int GetNumberofleaf(BiTree T)
{
//如果是空的就返回0
if(!T)
return 0;
//如果左右都为空就返回1
if(T->lchild==NULL&&T->rchild==NULL)
{
return 1;
}
//如果左右有不为空的就返回左右子树的和
else
{
return GetNumberofleaf(T->lchild)+GetNumberofleaf(T->rchild);
}
}
//求二叉树的层数
int GetDepth(BiTree T)
{
if(!T)
return 0;
return 1+max(GetDepth(T->lchild),GetDepth(T->rchild));
}
//结点个数
int GetNumberofNode(BiTree T)
{
if(!T)
return 0;
return 1+GetNumberofNode(T->lchild)+GetNumberofNode(T->rchild);
}
//销毁二叉树
Status DestoryBiTree(BiTree T)
{
if(!T)
return OK;
DestoryBiTree(T->lchild);
DestoryBiTree(T->rchild);
free(T);
T=NULL;
}
//实现递归遍历(中序)
//后序遍历
Status Traversal(BiTree T)
{
if(!T)
return OK;
cout<data<lchild);
Traversal(T->rchild);
return OK;
}
//非递归实现中序遍历
//即为用栈实现递归
//最开始让最左端的点在栈顶
Status InorderTraversal(BiTree T)
{
stacks;
while(T||!s.empty())
{
while(T)
{
s.push(T);
//若是前序遍历就如下
//cout<data<lchild;
}
BiTree p=s.top();
s.pop();
//若是中序遍历
cout<data<rchild;
}
}
//用两个栈实现后序遍历
//记一下吧,要用到一个辅助栈
//把左右的依次放进s,每次出来都放进hs
Status PostorderTraversal(BiTree T)
{
stacks;
stackhs;
s.push(T);
while(!s.empty())
{
BiTree p=s.top();
hs.push(p);
s.pop();
if(p->lchild)
s.push(p->lchild);
if(p->rchild)
s.push(p->rchild);
}
vector ans;
while(!hs.empty())
{
ans.push_back(hs.top()->data);
hs.pop();
}
return OK;
}
//交换左右子树
//递归实现
Status ExchangeBiTree(BiTree &B)
{
if(!B)
return OK;
BiTree p=NULL;
p=B->lchild;
B->lchild=B->rchild;
B->rchild=p;
if(B->lchild)
ExchangeBiTree(B->lchild);
if(B->rchild)
ExchangeBiTree(B->rchild);
return OK;
}
//非递归实现
//用队列实现
//这个实例证明了实现递归也可以用队列
Status ExchangeBiTree2(BiTree &B)
{
BiTree Queue[100];
int rear=0;
int front=-1;
Queue[rear++]=B;
while(rear!=front)
{
BiTree p=Queue[++front];
BiTree t=p->lchild;
p->lchild=p->rchild;
p->rchild=t;
if(p->lchild)
Queue[rear++]=p->lchild;
if(p->rchild)
Queue[rear++]=p->rchild;
}
return OK;
}
//如果是二叉树搜索树
//进行二叉搜索树的查找
BiTree SearchBiTree(BiTree B,BElemtype e)
{
if(!B)
return NULL;
if(B->data==e)
return B;
if(B->data>e)
SearchBiTree(B->rchild);
if(B->datarchild);
}
//二叉搜索树的插入
//无优化
Status InsertBiTree(BiTree &B,BElemtype e)
{
if(!B)
{
B->data=e;
}
if(edata)
{
InsertBiTree(B->lchild,e);
}
if(e>B->data)
{
InsertBiTree(B->rchild,e);
}
}
//二叉搜索树的删除
//删除结点没有左右子树
//有左子树
//有右子树
//左右子树都有
Status DeleteBiTree(BiTree &B,BElemtype e)
{
if(!B)
return ERROR;
BiTree p=SearchBiTree(B,e);
//是个叶子结点
if(!B->lchild&&!B->rchild)
{
B=NULL;
return OK;
}
//有左子树
else if(p->lchild&&!p->rchild)
{
BiTree Max=p->lchild;
BiTree pre=NULL;
while(Max->rchild)
{
p=Max;
Max=Max->rchild;
}
p->data=Max->data;
//如果最大值结点还有左子树
//就把左子树接在被删除节点的父节点的左子树上
if(Max->lchild)
{
pre->lchild=Max->lchild;
}
//没有左子树或者就是一个叶子结点就直接赋值为空
Max=NULL;
}
else//有右子树或者左右都有
//找右子树中最小的
{
BiTree Min=p->rchild;
BiTree pre=NULL;
while(Min->lchild)
{
p=Min;
Min=Min->lchild;
}
p->data=Min->data;
//如果最小值结点还有右子树
//就把右子树接在被删除节点的父节点的右子树上
if(Min->rchild)
{
pre->rchild=Min->rchild;
}
//没有右子树或者就是一个叶子结点就直接赋值为空
Min=NULL;
}
return OK;
}
满二叉树和完全二叉树
Huffman树并求Huffman编码
#include
using namespace std;
#define OK 1
#define ERROR -1
#define OVERFLOW -2
typedef int Status;
typedef char* HuffmanCode;
typedef struct
{
int weight;
int lchild;
int rchild;
int parent;
} HTNode,*HuffmanTree;
//找权值最小的没有parent结点的两个结点
void SelectHTode(HuffmanTree &HF,int upbound,int &s1,int &s2)
{
int min1=10000,min2=10000,num1=0,num2=0;
for(int i=1; i<=upbound; i++)
{
if(HF[i].parent==0&&HF[i].weightlchild=0;
p->parent=0;
p->rchild=0;
p->weight=w[i-1];
}
if(n==1)
return OK;
for(int i=n+1; i<=m; i++)
{
int s1,s2;
SelectHTode(HT,i-1,s1,s2);
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
HT[s1].parent=i;
HT[s2].parent=i;
}
return OK;
}
//自底向上找编码
Status FindHuffmanCode(HuffmanTree HT,HuffmanCode* HC,int n)
{
int p;
for(int i=1; i<=n; i++)
{
char *ans=(char*)malloc(sizeof(char)*(n+1));
ans[n]='\0';
p=HT[i].parent;
int pos=n-1;
while(p)
{
if(i==HT[i].lchild)
{
ans[pos--]='0';
}
else
{
ans[pos--]='1';
}
}
strcpy(HC[i],ans+pos+1);
ans=NULL;
}
}
题目:
1.某二叉树的后序和中序遍历序列正好一样,则该二叉树中的任何结点一定都无右孩子。
2.某二叉树的后序和中序遍历序列正好一样,则该二叉树中的任何结点一定都无左孩子。F
3.若一个结点是某二叉树的中序遍历序列的最后一个结点,则它必是该树的前序遍历序列中的最后一个结点。F
4.任何一棵二叉树的叶结点在先序、中序和后序遍历序列中的相对次序(不发生改变)
5.某二叉树的前序和后序遍历序列正好相反,则该二叉树一定是(高度等于其结点数).
6.设n、m为一棵二叉树上的两个结点,在中序遍历时,n在m前的条件是(n在m左边)
7.只有一个结点的二叉树的度为0 。 二叉树的左右子树可任意交换。
8.深度为K的完全二叉树的结点个数小于或等于深度相同的满二叉树。
9.二叉树若用顺序存储结构(数组)存放,则下列四种运算中的(层次遍历二叉树)最容易实现。
10.后序线索化二叉树,中序类推
11.下列线索二叉树中(用虚线表示线索),符合后序线索树定义的是:
12.存在一棵总共有2016个结点的二叉树,其中有16个结点只有一个孩子。F
2048-1=2047 2047-2016=31 31-16=15 是奇数不可能。
13.如果一棵非空k(k≥2)叉树T中每个非叶子结点都有k个孩子,则称T为正则k叉树。若T的高度为h(单结点的树h=1),则T的结点数最少为:(k(h−1)+1)
就是每一层都有k-1个叶子结点
14.如果一棵非空k(k≥2)叉树T中每个非叶子结点都有k个孩子,则称T为正则k叉树。若T有m个非叶子结点,则T中的叶子结点个数为:(m(k−1)+1)
每个非叶子节点,都会产生K个结点,总结点数为m*k-1,去除非叶子节点m*k-1-m
15.有一个四叉树,度2的结点数为2,度3的结点数为3,度4的结点数为4。问该树的叶结点个数是多少? 21
N个结点有N-1条边,4+9+16=29 29 +1=30 30-9=21
16。三叉树中,度为1的结点有5个,度为2的结点3个,度为3的结点2个,问该树含有几个叶结点?8
度和结点的个数不能混了,5+6+6=17 17-5-2-3=7 7+1=8
17.设高为h的二叉树(规定叶子结点的高度为1)只有度为0和2的结点,则此类二叉树的最少结点数和最多结点数分别为:2h−1, 2^h−1
这种 多叉树求最少结点的时候,不要想让最后一层少点,要让每一层都有K-1个叶子结点
18.对一棵平衡二叉树,所有非叶结点的平衡因子都是0,当且仅当该树是完全二叉树 F
可能为1
19.若二叉搜索树是有N个结点的完全二叉树,则不正确的说法是:最大值一定在叶结点上
20.若一棵AVL树有 28 个结点,则该树的最大深度为__。空树的深度定义为0。
知道层数得到总的结点的个数 2^n-1。n=5,得出来31,5+1=6;
21. 将 1, 2, 3, 6, 5, 4 顺序一个个插入一棵初始为空的AVL树,会经历下列哪些旋转?
一个“右-右”旋和两个“右-左”旋
浅析平衡二叉树的四种旋转_IT夜幕的博客-CSDN博客_平衡二叉树旋转
22.在下列所示的平衡二叉树中,插入关键字48后得到一棵新平衡二叉树。在新平衡二叉树中,关键字37所在结点的左、右子结点中保存的关键字分别是:24. 53
首先判断是RL型,因此先右旋,成为右右型然后左旋。
23.
下列叙述正确的是(D)。
A.任意一棵非空二叉搜索树,删除某结点后又将其插入,则所得二叉搜索树与删除前原二叉搜索树相同。
B.二叉树中除叶结点外, 任一结点X,其左子树根结点的值小于该结点(X)的值;其右子树根结点的值≥该结点(X)的值,则此二叉树一定是二叉搜索树。
//你要保证不是只针对所在树的根节点
C.虽然给出关键字序列的顺序不一样,但依次生成的二叉搜索树却是一样的。
D.在二叉搜索树中插入一个新结点,总是插入到最下层,作为新的叶子结点。