博客作业04--树
1.学习总结
1.1树结构思维导图
1.2 树结构学习体会
- 1.学树结构觉得有点吃力,构造树结构还不太熟悉,上机的时候就萌因为有很多的内容,很零碎,还不能很好的联会贯通
- 2.难点重要点很多,二叉树,哈夫曼树等等
- 3.很多题目是对方法理解了,但是如何用代码实现还是卡壳
2.PTA实验作业(4分)
2.1 题目1:7-3 jmu-ds-二叉树层次遍历
2.2 设计思路:
层次遍历:
void level(BTree bt){
定义一个静态局部变量flag=1
创建队列q
定义指针p
if(bt!=NULL)根节点入队
while(队列不为空){
p指针指向头结点
队头元素出队
if(flag){//第一个元素输出无空格处理
输出首节点的data;flag=0;
}
else 输出首节点的data(前面带空格)
若首节点左子树不为空,则入队
i若首节点右子树不为空,则入队
}
}
2.3 代码截图:
2.4 PTA提交列表说明
树为空的时候没有输出NULL导致部分正确
2.1 题目2: jmu-ds-二叉树叶子结点带权路径长度和
2.2 设计思路:
计算带权路径长度和函数:
static int L=0;//L为带权路径和
int wpl(BTree bt){
如果是空树 return 0;
如果是叶子节点{
L+=(bt->data-'0')*(bt->h-1);//将字符数字转化成数字,路径长度为高度-1
}
如果是左子树 wpl(bt->lchild);
如果是右字数 wpl(bt->rchild);
return L;
}
2.3 代码截图:
2.4 PTA提交列表说明
在DEVEC调试了多次输出结果不对,结果很大,发现这边写错了,一个是用的字符型输入,需要对数字进行处理,还有就是路径是h-1不是h
2.1 题目3:6-4 jmu-ds-表达式树
2.2 设计思路:
建树:
建立一个存放符号的栈op,和存放根结点的栈root
往符号栈op中存入#
while(字符串未遍历完)
如果是数字
定义一个根节点并初始化并且值为这个数字
将这个根节点入根节点栈root
否则
while(op栈的栈顶优先级大于此时遍历的符号)
定义一个根节点并初始化并且值为op栈顶元素
op栈顶元素出栈
root栈出栈两个元素作为刚定义的根节点的左右孩子
入栈这个根节点
如果(op栈的栈顶优先级小于此时遍历的符号)
将这个符号入栈到op栈
否则
op栈出栈
while(栈顶元素不为#即还有需要建立的结点)
定义一个根节点并初始化并且值为op栈顶元素
op栈顶元素出栈
root栈出栈两个元素作为刚定义的根节点的左右孩子
入栈这个根节点
根节点为此时root栈的栈顶
计算:(简要说明)
非递归后序遍历遇到数字入栈,遇到符号就出栈两个元素计算然后将结果入栈
最后的栈顶元素为结果
2.3 代码截图:
2.4 PTA提交列表说明
出错主要在于判断条件顺序没弄对,导致段错误,还有就是对于出栈栈顶元素顺序没搞清楚,写反了导致答案错误
3.1 PTA排名
3.2 我的得分:230
4. 阅读代码(必做,1分)
- 哈夫曼编码解码
#include<iostream>
#include<string>
using namespace std;
struct Node
{
double weight;
string ch;
string code;
int lchild, rchild, parent;
};
void Select(Node huffTree[], int *a, int *b, int n)//找权值最小的两个a和b
{
int i;
double weight = 0; //找最小的数
for (i = 0; i <n; i++)
{
if (huffTree[i].parent != -1) //判断节点是否已经选过
continue;
else
{
if (weight == 0)
{
weight = huffTree[i].weight;
*a = i;
}
else
{
if (huffTree[i].weight < weight)
{
weight = huffTree[i].weight;
*a = i;
}
}
}
}
weight = 0; //找第二小的数
for (i = 0; i < n; i++)
{
if (huffTree[i].parent != -1 || (i == *a))//排除已选过的数
continue;
else
{
if (weight == 0)
{
weight = huffTree[i].weight;
*b = i;
}
else
{
if (huffTree[i].weight < weight)
{
weight = huffTree[i].weight;
*b = i;
}
}
}
}
int temp;
if (huffTree[*a].lchild < huffTree[*b].lchild) //小的数放左边
{
temp = *a;
*a = *b;
*b = temp;
}
}
void Huff_Tree(Node huffTree[], int w[], string ch[], int n)
{
for (int i = 0; i < 2 * n - 1; i++) //初始过程
{
huffTree[i].parent = -1;
huffTree[i].lchild = -1;
huffTree[i].rchild = -1;
huffTree[i].code = "";
}
for (int i = 0; i < n; i++)
{
huffTree[i].weight = w[i];
huffTree[i].ch = ch[i];
}
for (int k = n; k < 2 * n - 1; k++)
{
int i1 = 0;
int i2 = 0;
Select(huffTree, &i1, &i2, k); //将i1,i2节点合成节点k
huffTree[i1].parent = k;
huffTree[i2].parent = k;
huffTree[k].weight = huffTree[i1].weight + huffTree[i2].weight;
huffTree[k].lchild = i1;
huffTree[k].rchild = i2;
}
}
void Huff_Code(Node huffTree[], int n)
{
int i, j, k;
string s = "";
for (i = 0; i < n; i++)
{
s = "";
j = i;
while (huffTree[j].parent != -1) //从叶子往上找到根节点
{
k = huffTree[j].parent;
if (j == huffTree[k].lchild) //如果是根的左孩子,则记为0
{
s = s + "0";
}
else
{
s = s + "1";
}
j = huffTree[j].parent;
}
cout << "字符 " << huffTree[i].ch << " 的编码:";
for (int l = s.size() - 1; l >= 0; l--)
{
cout << s[l];
huffTree[i].code += s[l]; //保存编码
}
cout << endl;
}
}
string Huff_Decode(Node huffTree[], int n,string s)
{
cout << "解码后为:";
string temp = "",str="";//保存解码后的字符串
for (int i = 0; i < s.size(); i++)
{
temp = temp + s[i];
for (int j = 0; j < n; j++)
{
if (temp == huffTree[j].code)
{
str=str+ huffTree[j].ch;
temp = "";
break;
}
else if (i == s.size()-1&&j==n-1&&temp!="")//全部遍历后没有
{
str= "解码错误!";
}
}
}
return str;
}
int main()
{
//编码过程
const int n=5;
Node huffTree[2 * n];
string str[] = { "A", "B", "C", "D", "E"};
int w[] = { 30, 30, 5, 20, 15 };
Huff_Tree(huffTree, w, str, n);
Huff_Code(huffTree, n);
//解码过程
string s;
cout << "输入编码:";
cin >> s;
cout << Huff_Decode(huffTree, n, s)<< endl;;
system("pause");
return 0;
}
编码的实现是先构造哈夫曼树,通过遍历哈夫曼树,从每个叶子结点开始向上遍历,如果该结点为父节点的左孩子,则在字符串后面追加“0”,如果为其右孩子,则在字符串后追加“1”。结束条件为没有父节点。将字符串倒序存入结点中。