西工大NOJ数据结构理论——018.建立二叉树的二叉链表(严6.65)

33 篇文章 8 订阅

刚点开这道题以后,我的反应是:

1.打开老师发的PPT:DS-Chap6,然后翻到第70页;

2.跟着图解,自己照着画了三四遍(其实是抄了三四遍;

3.然后自己出了一个比较简单的题:

   先序:ABDCE

   中序:BDACE

 因为这个简单,用的步骤少,反复做几次用的时间少,容易出思路,所以我就以它为例,自己想着构建了一棵二叉树。

4.把3.中的二叉树画了十来遍之后,心里大概有了个谱,然后在二叉树上每一次笔动一下,都问自己两个问题:1.为什么这样做?2.下一步该怎么做?每一次问完自己后,就把这2个问题的答案按顺序和层次写下来。(我发现,对于这2个问题的答案,就是代码直接翻译过来以后的结果

5.接着我回头看4.中写下来的答案,找出相同答案部分,这相同的部分就是递归函数的函数体。然后整理4.中写下来的答案。

6.然后,我在纸上把5.整理后的答案直接翻译成C代码

7.下面是惯例的一步:我在Dev上,用了10分钟把代码照着纸上写的敲了进去,然后又用了10分钟写了下主函数中的输入输出部分。

8.用了下面这个思路简单,步骤很少的例子测试,发现黑框框里没反应:

 9.然后一步步调试,发现原因呢,是因为一级指针不够用,所以引入了二级指针

10.修改成二级指针后,反反复复又改了很多遍(改的都是些带不带*,带不带&,然后变量名是不是对应上了这些问题,而递归思路却是正确的,所以没有改递归思路)。

11.最后再去提交,就成功AC啦!

 

好了,现在分享源码啦:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
typedef char DataType;
typedef struct BinTreeNode{
	DataType info;
	struct BinTreeNode* lchild;
	struct BinTreeNode* rchild;
}BinTreeNode,*PBinTreeNode; 

void InitializeBinTreeNode(PBinTreeNode PNode){
	//初始化二叉树中的单个结点 
	PNode->info='0';
	PNode->lchild=NULL;
	PNode->rchild=NULL;
}

PBinTreeNode CreateBinTreeNode(){
	//创建二叉树中的单个结点 
	PBinTreeNode PNode=(PBinTreeNode)malloc(sizeof(BinTreeNode));
	if(PNode==NULL){
		printf("out of space!");
	}else{
		InitializeBinTreeNode(PNode);
		return PNode;
	}
}

PBinTreeNode Recursion(char **pp_pre,char *begin,char *end){
	//根据先序和中序,创建一棵完整二叉树  
	PBinTreeNode cur=CreateBinTreeNode();
	cur->info=**pp_pre;
	char *temp;
	for(temp=begin;((*temp)!=(**pp_pre))&&(temp<=end);temp++);
	if(begin!=temp){
		(*pp_pre)++;
		cur->lchild=Recursion(pp_pre,begin,temp-1);
	}else{
		cur->lchild=NULL;
	}
	if(temp!=end){
		(*pp_pre)++;
		cur->rchild=Recursion(pp_pre,temp+1,end);
	}else{
		cur->rchild=NULL;
	}
	return cur;
}

void PostOrderOutput(PBinTreeNode ptr_node){
	//后序遍历一棵二叉树 
	if(ptr_node->lchild){
		PostOrderOutput(ptr_node->lchild);
	}
	if(ptr_node->rchild){
		PostOrderOutput(ptr_node->rchild);
	}
	printf("%c",ptr_node->info);
}

int main(){ 
	char pre[1000]={0};
	char in[1000]={0};
	scanf("%s%s",pre,in);
	char *p_pre=pre;
	//因为要确保递归过程中,所有函数都用同一个p_pre 
	//所以设置一个二级指针pp_pre 
	char **pp_pre=&p_pre;
	//下面指针begin和end都只用在数组in中 
	char *begin=in;
	char *end=begin+1;
	for(;*(end+1)!='\000';end++);
	//递归构建一棵二叉树 
	PBinTreeNode tree=Recursion(pp_pre,begin,end);
	//后序输出一棵二叉树 
	PostOrderOutput(tree);
	return 0;
}

 

 

 

西北工业大学NOJC程序设计习题答案(非本人制作,侵删) 1.“1“的传奇 2.A+B 3.A+BⅡ 4.AB 5.ACKERMAN 6.Arithmetic Progressions 7.Bee 8.Checksum algorithm 9.Coin Test 10.Dexter need help 11.Double 12.Easy problem 13.Favorite number 14.Graveyard 15.Hailstone 16.Hanoi Ⅱ 17.Houseboat 18.Music Composer 19.Redistribute wealth 20.Road trip 21.Scoring 22.Specialized Numbers 23.Sticks 24.Sum of Consecutive 25.Symmetric Sort 26.The Clock 27.The Ratio of gainers to losers 28.VOL大学乒乓球比赛 29.毕业设计论文打印 30.边沿与内芯的差 31.不会吧,又是A+B 32.不屈的小蜗 33.操场训练 34.插入链表节点 35.插入排序 36.插入字符 37.成绩表计算 38.成绩转换 39.出租车费 40.除法 41.创建与遍历职工链表 42.大数乘法 43.大数除法 44.大数加法 45.单词频次 46.迭代求根 47.多项式的猜想 48.二分查找 49.二分求根 50.发工资的日子 51.方差 52.分离单词 53.分数拆分 54.分数化小数 55.分数加减法 56.复数 57.高低交换 58.公园喷水器 59.韩信点兵 60.行程编码压缩算法 61.合并字符串 62.猴子分桃 63.火车站 64.获取指定二进制位 65.积分计算 66.级数和 67.计算A+B 68.计算PI 69.计算π 70.计算成绩 71.计算完全数 72.检测位图长宽 73.检查图像文件格式 74.奖金发放 75.阶乘合计 76.解不等式 77.精确幂乘 78.恐怖水母 79.快速排序 80.粒子裂变 81.链表动态增长或缩短 82.链表节点删除 83.两个整数之间所有的素数 84.路痴 85.冒泡排序 86.你会存钱吗 87.逆序整数 88.排列 89.排列分析 90.平均值函数 91.奇特的分数数列 92.求建筑高度 93.区间内素数 94.三点顺序 95.山迪的麻烦 96.删除字符 97.是该年的第几天 98.是该年的第几天? 99.数据加密 100.搜索字符 101.所有素数 102.探索合数世纪 103.特殊要求的字符串 104.特殊整数 105.完全数 106.王的对抗 107.危险的组合 108.文件比较 109.文章统计 110.五猴分桃 111.小型数据库 112.幸运儿 113.幸运数字”7“ 114.选择排序 115.寻找规律 116.循环移位 117.延伸的卡片 118.羊羊聚会 119.一维数组”赋值“ 120.一维数组”加法“ 121.勇闯天涯 122.右上角 123.右下角 124.圆及圆球等的相关计算 125.圆及圆球等相关计算 126.程序员添加行号 127.找出数字 128.找幸运数 129.找最大数 130.整数位数 131.重组字符串 132.子序列的和 133.子字符串替换 134.自然数立方的乐趣 135.字符串比较 136.字符串复制 137.字符串加密编码 138.字符串逆序 139.字符串排序 140.字符串替换 141.字符串左中右 142.组合数 143.最次方数 144.最大乘积 145.最大整数 146.最小整数 147.最长回文子串 148.左上角 149.左下角
哈夫曼编码是一种常用的数据压缩算法,可以将原始数据转换为更短的编码,从而减少存储空间。它的基本思想是:根据字符出现的频率,构建一颗二叉树,使得出现频率高的字符离根节点近,出现频率低的字符离根节点远。然后,对于每个字符,从根节点出发,沿着对应的路径到达该字符所在的叶子节点,记录下路径,作为该字符的编码。 哈夫曼编码的具体实现步骤如下: 1. 统计每个字符在原始数据中出现的频率。 2. 根据字符的频率构建哈夫曼树。构建方法可以采用贪心策略,每次选择出现频率最低的两个字符,将它们作为左右子节点,父节点的权值为两个子节点的权值之和。重复这个过程,直到只剩下一个根节点。 3. 对哈夫曼树进行遍历,记录下每个字符的编码,为了避免编码产生歧义,通常规定左子节点为0,右子节点为1。 4. 将原始数据中的每个字符,用它对应的编码来代替。这一步可以通过哈夫曼树来实现。 5. 将编码后的数据存储起来。此时,由于每个字符的编码长度不同,所以压缩后的数据长度也不同,但总体上来说,压缩效果通常是比较好的。 实现哈夫曼编码的关键在于构建哈夫曼树和计算每个字符的编码。构建哈夫曼树可以采用优先队列来实现,每次从队列中取出两个权值最小的节点,合并成一个节点,再将合并后的节点插入队列中。计算每个字符的编码可以采用递归遍历哈夫曼树的方式,从根节点出发,如果走到了左子节点,则将0添加到编码中,如果走到了右子节点,则将1添加到编码中,直到走到叶子节点为止。 以下是基于C++的代码实现,供参考: ```c++ #include <iostream> #include <queue> #include <string> #include <unordered_map> using namespace std; // 定义哈夫曼树节点的结构体 struct Node { char ch; // 字符 int freq; // 出现频率 Node* left; // 左子节点 Node* right; // 右子节点 Node(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {} }; // 定义哈夫曼树节点的比较函数,用于优先队列的排序 struct cmp { bool operator() (Node* a, Node* b) { return a->freq > b->freq; } }; // 构建哈夫曼树的函数 Node* buildHuffmanTree(unordered_map<char, int> freq) { priority_queue<Node*, vector<Node*>, cmp> pq; for (auto p : freq) { pq.push(new Node(p.first, p.second)); } while (pq.size() > 1) { Node* left = pq.top(); pq.pop(); Node* right = pq.top(); pq.pop(); Node* parent = new Node('$', left->freq + right->freq); parent->left = left; parent->right = right; pq.push(parent); } return pq.top(); } // 遍历哈夫曼树,计算每个字符的编码 void calcHuffmanCode(Node* root, unordered_map<char, string>& code, string cur) { if (!root) return; if (root->ch != '$') { code[root->ch] = cur; } calcHuffmanCode(root->left, code, cur + "0"); calcHuffmanCode(root->right, code, cur + "1"); } // 将原始数据编码成哈夫曼编码 string encode(string s, unordered_map<char, string> code) { string res; for (char c : s) { res += code[c]; } return res; } // 将哈夫曼编码解码成原始数据 string decode(string s, Node* root) { string res; Node* cur = root; for (char c : s) { if (c == '0') { cur = cur->left; } else { cur = cur->right; } if (!cur->left && !cur->right) { res += cur->ch; cur = root; } } return res; } int main() { string s = "abacabad"; unordered_map<char, int> freq; for (char c : s) { freq[c]++; } Node* root = buildHuffmanTree(freq); unordered_map<char, string> code; calcHuffmanCode(root, code, ""); string encoded = encode(s, code); string decoded = decode(encoded, root); cout << "Original string: " << s << endl; cout << "Encoded string: " << encoded << endl; cout << "Decoded string: " << decoded << endl; return 0; } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值