博客作业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”。结束条件为没有父节点。将字符串倒序存入结点中。

5. 代码Git提交记录截图

posted @ 2018-05-05 19:41  evfun  阅读(300)  评论(2编辑  收藏  举报