热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

哈夫曼树;二叉树;二叉排序树(BST)

优先队列:priority_queue<Type,Container,Functional>Type为数据类型,Container为保存数据的容器,Functional为元素比

优先队列:priority_queue
Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。
Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.
STL里面默认用的是 vector. 比较方式默认用 operator<, 所以如果你把后面俩个
参数缺省的话,优先队列就是大顶堆,队头元素最大。

而在求哈夫曼树中,我
们恰恰需要取得堆中最小的元素,于是我们使用如下语句定义一个小顶堆:
priority_queue , greater > Q;
关于堆的有关操作如下:
Q.push(x);
将元素 x 放入堆 Q 中。
int a = Q.top();
取出堆顶元素,即最小的元素保存在 a 中。
Q.pop();

弹出堆顶元素,取出后堆会自动调整为一个新的小顶堆。
它的定义与之前我们使用过的队列一样在标准模板库 queue 中,所以在使用
它之前我们必须做相应预处理。
#include

30.哈夫曼树(九度)

 1 30.哈夫曼树
2 时间限制:1
3 内存限制:32
4 特殊判题:否
5 题目描述:
6 哈夫曼树,第一行输入一个数 n,表示叶结点的个数。需要用这些叶结点生
7 成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即 weight,题目需要输出
8 所有结点的值与权值的乘积之和。
9 输入:
10 输入有多组数据。
11 每组第一行输入一个数 n,接着输入 n 个叶节点(叶节点权值不超过 100,
12 2<=n<=1000)。
13 输出:
14 输出权值。
15 样例输入:
16 5
17 1 2 2 5 9
18 样例输出:
19 37
View Code

 

 1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std;
8
9 priority_queue<int , vector<int> , greater<int> > Q; //建立一个小顶堆
10 int main () {
11 int n;
12 while (scanf ("%d",&n) != EOF) {
13 while(Q.empty() == false) Q.pop(); //清空堆中元素
14 for (int i = 1;i <= n;i ++) { //输入n个叶子结点权值
15 int x;
16 scanf ("%d",&x);
17 Q.push(x); //将权值放入堆中
18 }
19 int ans = 0; //保存答案
20 while(Q.size() > 1) { //当堆中元素大于1个
21 int a = Q.top();
22 Q.pop();
23 int b = Q.top();
24 Q.pop(); //取出堆中两个最小元素,他们为同一个结点的左右儿子,且该双亲结点的权值为它们的和
25 ans += a + b; //该父亲结点必为非叶子结点,固累加其权值
26 Q.push(a + b); //将该双亲结点的权值放回堆中
27 }
28 printf("%d\n",ans); //输出答案
29 }
30 return 0;
31 }
View Code

 

32.二叉树遍历(jiu du)

 1 二叉树遍历(九度教程第 32 题)
2 时间限制:1
3 内存限制:32
4 特殊判题:否题目描述:
5 二叉树的前序、中序、后序遍历的定义:
6 前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树;
7 中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树;
8 后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
9 给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍
10 历与中序遍历能够唯一确定后序遍历)。
11 输入:
12 两个字符串,其长度 n 均小于等于 26
13 第一行为前序遍历,第二行为中序遍历。二叉树中的结点名称以大写字母表
14 示:A,B,C....最多 26 个结点。
15 输出:
16 输入样例可能有多组,对于每组测试样例,输出一行,为后序遍历的字符串。
17 样例输入:
18 ABC
19 BAC
20 FDXEAG
21 XDEFAG
22 样例输出:
23 BCA
24 XEDGAF
Problem

 

 

 1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include <string.h>
9 using namespace std;
10 struct Node { //树结点结构体
11 Node *lchild; //左儿子指针
12 Node *rchild; //右儿子指针
13 char c; //结点字符信息
14 }Tree[50]; //静态内存分配数组
15 int loc; //静态数组中已经分配的结点个数
16 Node *creat() { //申请一个结点空间,返回指向其的指针
17 Tree[loc].lchild = Tree[loc].rchild = NULL; cout <' ';//初始化左右儿子为空
18 return &Tree[loc ++]; //返回指针,且loc累加
19 }
20 char str1[30] , str2[30]; //保存前序和中序遍历结果字符串
21 void postOrder(Node *T) { //后序遍历
22 if (T -> lchild != NULL) { //若左子树不为空
23 postOrder(T -> lchild); //递归遍历其左子树
24 }
25 if (T -> rchild != NULL) { //若右子树不为空
26 postOrder(T -> rchild); //递归遍历其右子树
27 }
28 printf("%c",T -> c); //遍历该结点,输出其字符信息
29 }
30 Node *build(int s1,int e1,int s2,int e2) { //由字符串的前序遍历和中序遍历还原树,并返回其根节点,其中前序遍历结果为由str1[s1]到str1[e1],中序遍历结果为str2[s2]到str2[e2]
31 Node* ret = creat(); //为该树根节点申请空间
32 ret -> c = str1[s1]; //该结点字符为前序遍历中第一个字符
33 int rootIdx;
34 for (int i = s2;i <= e2;i ++) {//查找该根节点字符在中序遍历中的位置
35 if (str2[i] == str1[s1]) {
36 rootIdx = i;
37 break;
38 }
39 }
40 if (rootIdx != s2) { //若左子树不为空
41 ret -> lchild = build(s1 + 1,s1 + (rootIdx - s2),s2,rootIdx - 1); //递归还原其左子树
42 }
43 if (rootIdx != e2) { //若右子树不为空
44 ret -> rchild = build(s1 + (rootIdx - s2) + 1,e1,rootIdx + 1,e2); //递归还原其右子树
45 }
46 return ret; //返回根节点指针
47 }
48 int main () {
49 while (scanf ("%s",str1) != EOF) {
50 scanf ("%s",str2); //输入
51 loc = 0; //初始化静态内存空间中已经使用结点个数为0
52 int L1 = strlen(str1);
53 int L2 = strlen(str2); //计算两个字符串长度
54 Node *T = build(0,L1 - 1,0,L2 - 1); //还原整棵树,其根结点指针保存在T中
55 postOrder(T); //后序遍历
56 printf("\n"); //输出换行
57 }
58 return 0;
59 }
View Code

 

35.二叉排序树 (Binary Search Tree),(又:二叉搜索树,二叉查找树

由于各个数字插入的顺序不同,所得到的二叉排序树的形态也很可能不同,
所以不同的插入顺序对二叉排序树的形态有重要的影响。但是,所有的二叉排序
树都有一个共同的特点:若对二叉排序树进行中序遍历,那么其遍历结果必然是
一个递增序列,这也是二叉排序树名字的来由,通过建立二叉排序树就能对原无
序序列进行排序,并实现动态维护。

 

 13.5 二叉排序树 (九度教程第 3 5 题)
2 时间限制:1
3 内存限制:32
4 特殊判题:否
5 题目描述:
6 输入一系列整数,建立二叉排序数,并进行前序,中序,后序遍历。
7 输入:
8 输入第一行包括一个整数 n(1<=n<=100)。接下来的一行包括 n 个整数。
9 输出:
10 可能有多组测试数据,对于每组数据,将题目所给数据建立一个二叉排序树,
11 并对二叉排序树进行前序、中序和后序遍历。每种遍历结果输出一行。每行最后
12 一个数据之后有一个空格。
13 样例输入:
14 5
15 1 6 5 9 8
16 样例输出:
17 1 6 5 9 8
18 1 5 6 8 9
19 5 8 9 6 1
20 提示:
21 输入中可能有重复元素,但是输出的二叉树遍历序列中重复元素不用输出。
problem

 

 1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include <string.h>
9 using namespace std;
10 struct Node { //二叉树结构体
11 Node *lchild; //左儿子指针
12 Node *rchild; //右儿子指针
13 int c;//保存数字
14 }Tree[110]; //静态数组
15 int loc; //静态数组中被使用元素个数
16 Node *creat() { //申请未使用的结点
17 Tree[loc].lchild = Tree[loc].rchild = NULL;
18 return &Tree[loc ++];
19 }
20 void postOrder(Node *T) { //后序遍历
21 if (T -> lchild != NULL) {
22 postOrder(T -> lchild);
23 }
24 if (T -> rchild != NULL) {
25 postOrder(T -> rchild);
26 }
27 printf("%d ",T -> c);
28 }
29 void inOrder(Node *T) { //中序遍历
30 if (T -> lchild != NULL) {
31 inOrder(T -> lchild);
32 }
33 printf("%d ",T -> c);
34 if (T -> rchild != NULL) {
35 inOrder(T -> rchild);
36 }
37 }
38 void preOrder(Node *T) { //前序遍历
39 printf("%d ",T -> c);
40 if (T -> lchild != NULL) {
41 preOrder(T -> lchild);
42 }
43 if (T -> rchild != NULL) {
44 preOrder(T -> rchild);
45 }
46 }
47 Node *Insert(Node *T,int x) { //插入数字
48 if (T == NULL) { //若当前树为空
49 T = creat(); //建立结点
50 T -> c = x; //数字直接插入其根结点
51 return T; //返回根结点指针
52 }
53 else if (x c) //若x小于根结点数值
54 T -> lchild = Insert(T -> lchild,x); //插入到左子树上
55 else if (x > T->c) //若x大于根结点数值
56 T -> rchild = Insert(T -> rchild,x); //插入到右子树上.若根结点数值与x一样,根据题目要求直接忽略
57 return T; //返回根节点指针
58 }
59 int main () {
60 int n;
61 while (scanf ("%d",&n) != EOF) {
62 loc = 0;
63 Node *T = NULL; //二叉排序树树根结点为空
64 for (int i = 0;i //依次输入n个数字
65 int x;
66 scanf ("%d",&x);
67 T = Insert(T,x); //插入到排序树中
68 }
69 preOrder(T); //前序遍历
70 printf("\n"); //输出空行
71 inOrder(T); //中序遍历
72 printf("\n");
73 postOrder(T); //后序遍历
74 printf("\n");
75 }
76 return 0;
77 }
View Code

 

 

 13.6 二叉搜索树(九度教程第 36 题)
2 时间限制:1
3 内存限制:32
4 特殊判题:否
5 题目描述:
6 判断两序列是否为同一二叉搜索树序列
7 输入:
8 开始一个数 n,(1<=n<=20) 表示有 n 个需要判断,n= 0 的时候输入结束。
9 接下去一行是一个序列,序列长度小于 10,包含(0~9)的数字,没有重复数字,
10 根据这个序列可以构造出一颗二叉搜索树。
11 接下去的 n 行有 n 个序列,每个序列格式跟第一个序列一样,请判断这两个
12 序列是否能组成同一颗二叉搜索树。
13 输出:
14 如果序列相同则输出 YES,否则输出 NO
15 样例输入:
16 2
17 567432
18 543267
19 576342
20 0
21 样例输出:
22 YES
23 NO
problem

 

 1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include <string.h>
9 using namespace std;
10
11 struct Node { //树节点结构体
12 Node *lchild;
13 Node *rchild;
14 int c;
15 }Tree[110];
16 int loc;
17 Node *creat() { //申请结点空间
18 Tree[loc].lchild = Tree[loc].rchild = NULL;
19 return &Tree[loc ++];
20 }
21 char str1[25] , str2[25]; //保存二叉排序树的遍历结果,将每一棵树的前序遍历得到的字符串与中序遍历得到的字符串连接,得到遍历结果字符串
22 int size1 , size2; //保存在字符数组中的遍历得到字符个数
23 char *str; //当前正在保存字符串
24 int *size; //当前正在保存字符串中字符个数
25 void postOrder(Node *T) { //前序遍历
26 if (T -> lchild != NULL) {
27 postOrder(T -> lchild);
28 }
29 if (T -> rchild != NULL) {
30 postOrder(T -> rchild);
31 }
32 str[ (*size) ++ ] = T -> c + '0'; //将结点中的字符放入正在保存的字符串中
33 }
34 void inOrder(Node *T) { //中序遍历
35 if (T -> lchild != NULL) {
36 inOrder(T -> lchild);
37 }
38 str[ (*size) ++ ] = T -> c + '0';
39 if (T -> rchild != NULL) {
40 inOrder(T -> rchild);
41 }
42 }
43 Node *Insert(Node *T,int x) { //将数字插入二叉树
44 if (T == NULL) {
45 T = creat();
46 T -> c = x;
47 return T;
48 }
49 else if (x c)
50 T -> lchild = Insert(T -> lchild,x);
51 else if (x > T->c)
52 T -> rchild = Insert(T -> rchild,x);
53 return T;
54 }
55 int main () {
56 int n;
57 char tmp[12];
58 while (scanf ("%d",&n) != EOF && n != 0) {
59 loc = 0; //初始化静态空间为未使用
60 Node *T = NULL;
61 scanf ("%s",tmp); //输入字符串
62 for (int i = 0;tmp[i] != 0;i ++) {
63 T = Insert(T,tmp[i] - '0'); //按顺序将数字插入二叉排序树
64 }
65 size1 = 0; //保存在第一个字符串中的字符初始化为0
66 str = str1; //将正在保存字符串设定为第一个字符串
67 size = &size1; //将正在保存字符串中的字符个数指针指向size1
68 postOrder(T); //前序遍历
69 inOrder(T); //中序遍历
70 str1[ size1 ] = 0; //向第一个字符串的最后一个字符后添加空字符,方便使用字符串函数
71 while(n -- != 0) { //输入n个其它字符串
72 scanf ("%s",tmp); //输入
73 Node *T2 = NULL;
74 for (int i = 0;tmp[i] != 0;i ++) { //建立二叉排序树
75 T2 = Insert(T2,tmp[i] - '0');
76 }
77 size2 = 0; //第二个字符串保存字符初始化为0
78 str = str2; //将正在保存字符串设定为第二个字符串
79 size = &size2; //正在保存字符串中字符数量指针指向size2
80 postOrder(T2); //前序遍历
81 inOrder(T2); //中序遍历
82 str2[ size2 ] = 0; //字符串最后添加空字符
83 puts (strcmp(str1,str2) == 0 ? "YES" : "NO"); //比较两个遍历字符串,若相同则输出YES,否则输出NO
84 }
85 }
86 return 0;
87 }
View Code

 


推荐阅读
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 006_Redis的List数据类型
    1.List类型是一个链表结构的集合,主要功能有push,pop,获取元素等。List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • C++语言入门:数组的基本知识和应用领域
    本文介绍了C++语言的基本知识和应用领域,包括C++语言与Python语言的区别、C++语言的结构化特点、关键字和控制语句的使用、运算符的种类和表达式的灵活性、各种数据类型的运算以及指针概念的引入。同时,还探讨了C++语言在代码效率方面的优势和与汇编语言的比较。对于想要学习C++语言的初学者来说,本文提供了一个简洁而全面的入门指南。 ... [详细]
author-avatar
mobiledu2502908793
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有