一个不知名大学生,江湖人称菜狗
original author: jacky Li
Email : [email protected]
Last edited: 2022.11.17
"""
目录
算法5.1-5.6
第1关:5.1,5.3中序遍历的递归算法
任务描述
相关知识
编程要求
测试说明
参考代码
第2关:5.2中序遍历的非递归算法
任务描述
相关知识
编程要求
测试说明
参考代码
第3关:5.4复制二叉树
任务描述
相关知识
编程要求
测试说明
参考代码
第4关:5.5计算二叉树的深度
任务描述
相关知识
编程要求
测试说明
参考代码
第5关:5.6统计二叉树中节点的个数
任务描述
相关知识
编程要求
测试说明
参考代码
算法5.7-5.9线索二叉树
第1关:5.7-5.9线索化遍历
任务描述
相关知识
编程要求
测试说明
参考代码
算法5.10-5.11构造哈夫曼树求哈夫曼编码
第1关:例子5.3使用哈夫曼编码
任务描述
编程要求
测试说明
参考代码
算法5.12-5.13表达式求值
第1关:表达式树的求值
任务描述
编程要求
测试说明
参考代码
本关任务:编写一个中序遍历的递归算法,包含算法5.1遍历算法和5.3先序遍历建立二叉树。
为了完成本关任务,你需要掌握:1.如何中序遍历二叉树 2.如何先序遍历建立二叉树。
根据提示,在右侧编辑器补充代码,并输出中序遍历的二叉树。
平台会对你编写的代码进行测试:
测试输入:ABC##DE#G##F###;
预期输出:CBEGDFA
开始你的任务吧,祝你成功!
//算法5.1 中序遍历的递归算法
#include
using namespace std;
typedef struct BiNode{ //二叉链表定义
char data;
struct BiNode *lchild,*rchild;
}BiTNode,*BiTree;
//用算法5.3 先序遍历的顺序建立二叉链表
void CreateBiTree(BiTree &T){
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin>>ch;
if(ch=='#') T=NULL;
else{
T=new BiTNode;
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
} //CreateBiTree
void InOrderTraverse(BiTree T)
{
//中序遍历二叉树T的递归算法
if(T)
{
InOrderTraverse(T -> lchild);
cout<< T -> data;
InOrderTraverse(T -> rchild);
}
}
int main(){
BiTree tree;
CreateBiTree(tree);
InOrderTraverse(tree);
cout<
本关任务:编写一个中序遍历的非递归算法,包含算法5.2非递归遍历算法和5.3先序遍历建立二叉树。
为了完成本关任务,你需要掌握:1.如何中序非递归遍历二叉树 2.如何先序遍历建立二叉树。
根据提示,在右侧编辑器补充代码,并输出中序遍历的二叉树。
平台会对你编写的代码进行测试:
测试输入:ABC##DE#G##F###;
预期输出:CBEGDFA
开始你的任务吧,祝你成功!
//算法5.2 中序遍历的非递归算法
#include
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//链栈的定义
typedef struct StackNode
{
BiTNode data;
struct StackNode *next;
}StackNode,*LinkStack;
//用算法5.3 先序遍历的顺序建立二叉链表
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
void InitStack(LinkStack &S)
{
//构造一个空栈S,栈顶指针置空
S=NULL;
}
bool StackEmpty(LinkStack S)
{
if(!S)
return true;
return false;
}
void Push(LinkStack &S,BiTree e)
{
//在栈顶插入元素*e
StackNode *p=new StackNode;
p->data=*e;
p->next=S;
S=p;
}
void Pop(LinkStack &S,BiTree e)
{
if(S!=NULL)//原书上写的是if(S==NULL)return ERROR;
{
*e=S->data;
StackNode *p=S;
S=S->next;
delete p;
}
}
void InOrderTraverse1(BiTree T)
{
// 中序遍历二叉树T的非递归算法
LinkStack S;
InitStack(S);
BiTree p, q;
p = T, q = new BiTNode;
while(p || !StackEmpty(S))
{
if(p)
{
Push(S, p);
p = p -> lchild;
}
else
{
Pop(S, q);
cout << q -> data;
p = q -> rchild;
}
}
} // InOrderTraverse
int main()
{
BiTree tree;
CreateBiTree(tree);
InOrderTraverse1(tree);
cout<
本关任务:编写一个中序遍历的递归算法,包含算法5.4复制二叉树。
为了完成本关任务,你需要掌握:1.如何中序遍历二叉树 2.如何先序遍历建立二叉树 3.如何复制二叉树。
根据提示,在右侧编辑器补充代码,并输出复制二叉树的中序遍历结果。
平台会对你编写的代码进行测试:
测试输入:ABC##DE#G##F###;
预期输出:CBEGDFA
开始你的任务吧,祝你成功!
//算法5.4 复制二叉树
#include
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//用算法5.3建立二叉链表
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
void Copy(BiTree T, BiTree &NewT)
{
/***********************Begin******************/
if(T == NULL)
{
NewT = NULL;
return;
}
NewT = new BiTNode;
NewT -> data = T -> data;
Copy(T -> lchild, NewT -> lchild);
Copy(T -> rchild, NewT -> rchild);
/**********************End*******************/
} //CopyBiTree
//用算法5.1 中序遍历的递归算法
void InOrderTraverse(BiTree T)
{
//中序遍历二叉树T的递归算法
if(T){
InOrderTraverse(T->lchild);
cout << T->data;
InOrderTraverse(T->rchild);
}
}
int main()
{
BiTree tree,new_tree;
CreateBiTree(tree);
Copy(tree,new_tree);
InOrderTraverse(new_tree);
cout<
本关任务:编写一个计算二叉树深度的算法,如5.5所示。
为了完成本关任务,你需要掌握:1.如何中序遍历二叉树 2.如何先序遍历建立二叉树 3.如何计算二叉树的深度。
根据提示,在右侧编辑器补充代码,并输出二叉树的深度。
平台会对你编写的代码进行测试:
测试输入:ABC##DE#G##F###
预期输出:5
开始你的任务吧,祝你成功!
//算法5.5 计算二叉树的深度
#include
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//用算法5.3建立二叉链表
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
int Depth(BiTree T)
{
if(T == NULL) return 0;
else
{
int m = Depth(T -> lchild);
int n = Depth(T -> rchild);
if(m > n) return (m + 1);
else return (n + 1);
}
}
int main()
{
BiTree tree;
CreateBiTree(tree);
cout << Depth(tree) << endl;
}
本关任务:编写一个计算二叉树中节点个数的算法,如5.5所示。
为了完成本关任务,你需要掌握:1.如何中序遍历二叉树 2.如何先序遍历建立二叉树 3.如何统计二叉树中的节点。
根据提示,在右侧编辑器补充代码,并输出二叉树的节点个数。
平台会对你编写的代码进行测试:
测试输入:ABC##DE#G##F###
预期输出:7
开始你的任务吧,祝你成功!
//算法5.6 统计二叉树中结点的个数
#include
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//用算法5.3建立二叉链表
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
int NodeCount(BiTree T)
{
if(T == NULL) return 0;
else return NodeCount(T -> lchild) + NodeCount(T -> rchild) + 1;
}
int main()
{
BiTree tree;
CreateBiTree(tree);
cout << NodeCount(tree) << endl;
}
本关任务:编写一个遍历线索二叉树的程序,包含算法5.7、算法5.8和算法5.9。
为了完成本关任务,你需要掌握:1.如何以节点p为根的子树线索化 2.带头结点的二叉树中序线索化 3.遍历线索二叉树。
根据提示,在右侧编辑器补充代码,并输出线索二叉树中的节点。
平台会对你编写的代码进行测试:
测试输入:ABC##DE#G##F###
预期输出:CBEGDFA
开始你的任务吧,祝你成功!
//算法5.9 遍历中序线索二叉树
#include
using namespace std;
//二叉树的二叉线索类型存储表示
typedef struct BiThrNode
{
char data; //结点数据域
struct BiThrNode *lchild,*rchild; //左右孩子指针
int LTag,RTag;
}BiThrNode,*BiThrTree;
//全局变量pre
BiThrNode *pre=new BiThrNode;
//用算法5.3建立二叉链表
void CreateBiTree(BiThrTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else
{
T=new BiThrNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
//用算法5.7以结点P为根的子树中序线索化
void InThreading(BiThrTree p)
{
//pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索
if(p)
{
InThreading(p -> lchild); //左子树递归线索化
if(!p -> lchild) //p的左孩子为空
{
p -> LTag = 1; //给p加上左线索
p -> lchild = pre; //p的左孩子指针指向pre(前驱)
}
else p -> LTag = 0;
if(!pre -> rchild) //pre的右孩子为空
{
pre -> RTag = 1; //给pre加上右线索
pre -> rchild = p; //pre的右孩子指针指向p(后继)
}
else pre -> RTag = 0;
pre = p; //保持pre指向p的前驱
InThreading(p -> rchild); //右子树递归线索化
}
}//InThreading
//用算法5.8带头结点的中序线索化
void InOrderThreading (BiThrTree &Thrt,BiThrTree T)
{
//中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
Thrt = new BiThrNode; //建头结点
Thrt -> LTag = 0; //头结点有左孩子,若树非空,则其左孩子为树根
Thrt -> RTag = 1; //头结点的右孩子指针为右线索
Thrt -> rchild = Thrt; //初始化时右指针指向自己
if(!T) Thrt -> lchild = Thrt; //若树为空,则左指针也指向自己
else
{
Thrt -> lchild = T; pre = Thrt;//头结点的左孩子指向根,pre初值指向头结点
InThreading(T); //调用算法,对以T为根的二叉树进行中序线索化
pre -> rchild = Thrt; //算法,结束后,pre为最右结点,pre的右线索指向头结点
pre -> RTag = 1;
Thrt -> rchild = pre; //头结点的右线索指向pre
}
} //InOrderThreading
void InOrderTraverse_Thr(BiThrTree T)
{
//T指向头结点,头结点的左链lchild指向根结点,可参见线索化算法5.8。
//中序遍历二叉线索树T的非递归算法,对每个数据元素直接输出
BiThrTree p;
p = T -> lchild; //p指向根结点
while(p != T)
{ //空树或遍历结束时,p==T
while(p -> LTag == 0) //沿左孩子向下
p = p -> lchild; //访问其左子树为空的结点
cout << p -> data;
while(p -> RTag == 1 && p -> rchild != T)
{
p = p -> rchild; //沿右线索访问后继结点
cout << p -> data;
}
p = p -> rchild;
}
} //InOrderTraverse_Thr
int main()
{
pre->RTag=1;
pre->rchild=NULL;
BiThrTree tree,Thrt;
CreateBiTree(tree);
InOrderThreading(Thrt,tree);
InOrderTraverse_Thr(Thrt);
cout<
本关任务:编写一个哈夫曼编码程序。
根据提示,在右侧编辑器补充代码。
平台会对你编写的代码进行测试:输入的第一行为叶子节点个数n,第二行分别是n个节点所对应的权值。输出为上述权值对应节点的哈夫曼编码。
测试输入: 8
5 29 7 8 14 23 3 11预期输出:
0001
10
1110
1111
110
01
0000
001
开始你的任务吧,祝你成功!
//算法5.11 根据赫夫曼树求赫夫曼编码
#include
#include
using namespace std;
typedef struct
{
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
void Select(HuffmanTree HT,int len,int &s1,int &s2)
{
int i, min1 = 0x3f3f, min2 = 0x3f3f;//规定一个特别大的数
for(i = 1; i <= len; i ++)
if(HT[i].parent == 0 && min1 > HT[i].weight)
min1 = HT[i].weight, s1 = i;
for(i = 1; i <= len; i ++) //注意这个I!=*s1标记min
if(i != s1 && HT[i].parent == 0)
if(HT[i].weight < min2)
min2 = HT[i].weight, s2 = i;
}
//用算法5.10构造赫夫曼树
void CreatHuffmanTree(HuffmanTree &HT,int n)
{
//构造赫夫曼树HT
if(n <= 1) return;
int m = 2 * n - 1;
HT = new HTNode[m + 1];
for(int i = 1; i <= m; i ++)
HT[i].parent = 0, HT[i].lchild = 0, HT[i].rchild = 0;
for(int i = 1; i <= n; i ++) cin >> HT[i].weight;
for(int i=n+1;i<=m;i++)
{
int s1, s2;
Select(HT, i - 1, s1, s2);
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
} // CreatHuffmanTree
void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
{
//从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中
char *cd;
HC = new char*[n + 1];
cd = new char[n];
cd[n - 1] = '\0';
for(int i = 1; i <= n; i ++)
{
int start = n - 1;
int c = i, f = HT[i].parent;
while(f != 0)
{
-- start;
if(HT[f].lchild == c) cd[start] = '0';
else cd[start] = '1';
c = f, f = HT[f].parent;
}
HC[i] = new char[n - start];
strcpy(HC[i], &cd[start]);
}
delete cd;
} // CreatHuffanCode
void show(HuffmanTree HT,HuffmanCode HC)
{
for(int i=1;i<=sizeof(HC);i++)
cout << HC[i]<< endl;
}
int main()
{
HuffmanTree HT;
HuffmanCode HC;
int n;
cin>>n; //输入赫夫曼树的叶子结点个数
CreatHuffmanTree(HT,n);
CreatHuffmanCode(HT,HC,n);
show(HT,HC);
return 0;
}
本关任务:编写一个表达式树求值的程序。
根据提示,在右侧编辑器补充代码。
平台会对你编写的代码进行测试:输入为一个表达式以#号结束,中间的计算过程需要是个位数。
测试输入: 3+(2+3)/5-2*2
预期输出: 0
开始你的任务吧,祝你成功!
//利用二叉树求解表达式的值
#include
#include
#define ERROR -1
#define MAXSIZE 100
using namespace std;
typedef struct BiTNode{ //二叉树的二叉链表存储表示
char data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef struct{ // 字符栈定义
char *base;
char *top;
int stacksize;
}SqStack;
typedef struct{ //树栈定义
BiTree *base;
BiTree *top;
int stacksize;
}BiTreeStack;
void InitStack(SqStack &S){ //字符栈初始化
S.base=new char[MAXSIZE];
if(!S.base) exit(-1);
S.top=S.base;
S.stacksize=MAXSIZE;
}
void InitBiTreeStack(BiTreeStack &S){ //树栈初始化
S.base=new BiTree[MAXSIZE];
if(!S.base) exit(-1);
S.top=S.base;
S.stacksize=MAXSIZE;
}
void Push(SqStack &S,char e) //字符栈入栈
{
if(S.top-S.base==S.stacksize) return ;
*S.top=e;
S.top++;
}
void PushBiTree(BiTreeStack &S,BiTree e) //树栈入栈
{
if(S.top-S.base==S.stacksize) return ;
*S.top=e;
S.top++;
}
void Pop(SqStack &S,char &e) //字符栈出栈
{
if(S.top==S.base) return;
e=*--S.top;
}
void PopBiTree(BiTreeStack &S,BiTree &e) //树栈出栈
{
if(S.top==S.base) return;
e=*--S.top;
}
char GetTop(SqStack &S) //字符栈得到栈顶函数
{
if(S.top==S.base) exit(1);
return *(S.top-1);
}
char Precede(char t1,char t2)
{ /* 根据教科书表3.1,判断两符号的优先关系 */
char f;
switch(t2)
{
case '+':if(t1=='('||t1=='#')
f='<';
else
f='>';
break;
case '-':if(t1=='('||t1=='#')
f='<';
else
f='>';
break;
case '*':if(t1=='*'||t1=='/'||t1==')')
f='>';
else
f='<';
break;
case '/':if(t1=='*'||t1=='/'||t1==')')
f='>';
else
f='<';
break;
case '(':if(t1!=')')
f='<';
break;
case')':if(t1=='(')
f='=';
else
f='>';
break;
case'#':if(t1=='#')
f='=';
else
f='>';
}
return f;
}
int In(char c)
{ /* 判断c是否为运算符 */
switch(c)
{
case '+':
case'-':
case'*':
case '/':
case'#':
case '(':
case')':return 1;break;
default:return 0;
}
}
int GetValue(char theta,int a,int b) //进行运算的函数
{
int c;
switch(theta)
{
case '+':c=a+b;break;
case'-':c=a-b;break;
case'*':c=a*b;break;
case'/':c=a/b;break;
default:
break;
}
return c;
}
void CreateExpTree(BiTree &T,BiTree a,BiTree b,char ch){ //简单二叉树的创建
T=new BiTNode;
T->data=ch;
T->lchild=a;
T->rchild=b;
}
void InitExpTree(BiTree &T) //算法5.12 表达式树的创建
{
SqStack OPTR;
BiTreeStack EXPT;
char ch, theta, x;
BiTree a, b;
InitStack(OPTR); Push(OPTR,'#');
InitBiTreeStack(EXPT);
cin >> ch;
while(ch != '#' || GetTop(OPTR) != '#')
{
if(!In(ch))
{
CreateExpTree(T, NULL, NULL, ch);
PushBiTree(EXPT, T);
cin >> ch;
}//*q
else
{
switch(Precede(GetTop(OPTR), ch))
{
case'<':
Push(OPTR, ch);
cin >> ch;
break;
case'>':
Pop(OPTR, theta);
PopBiTree(EXPT, b); PopBiTree(EXPT, a);
CreateExpTree(T,a,b,theta);
PushBiTree(EXPT, T);
break;
case'=':
Pop(OPTR,x);cin>>ch;
break;
}
}
}
}
int EvaluateExTree(BiTree T){ //算法5.13 表达式树的求值
int lvalue=0,rvalue=0;
if(T->lchild==NULL&&T->rchild==NULL) return T->data-'0';
else
{
lvalue=EvaluateExTree(T->lchild);
rvalue=EvaluateExTree(T->rchild);
return GetValue(T->data,lvalue,rvalue);
}
}
int main()
{
BiTree T;
InitExpTree(T); //创建表达式树
cout<