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


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

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

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

    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 <algorithm>
     2 #include <functional>
     3 #include <array>
     4 #include <iostream>
     5 #include <limits.h>
     6 #include <queue>
     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
    ",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 均小于等于 2613 第一行为前序遍历,第二行为中序遍历。二叉树中的结点名称以大写字母表
    14 示:A,B,C....最多 26 个结点。
    15 输出:
    16 输入样例可能有多组,对于每组测试样例,输出一行,为后序遍历的字符串。
    17 样例输入:
    18 ABC
    19 BAC
    20 FDXEAG
    21 XDEFAG
    22 样例输出:
    23 BCA
    24 XEDGAF
    Problem
     1 #include <algorithm>
     2 #include <functional>
     3 #include <array>
     4 #include <iostream>
     5 #include <limits.h>
     6 #include <queue>
     7 #include <stdio.h>
     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 << loc << ' ';//初始化左右儿子为空
    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("
    "); //输出换行
    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 <algorithm>
     2 #include <functional>
     3 #include <array>
     4 #include <iostream>
     5 #include <limits.h>
     6 #include <queue>
     7 #include <stdio.h>
     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 < T->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;i ++) { //依次输入n个数字
    65             int x;
    66             scanf ("%d",&x);
    67             T = Insert(T,x); //插入到排序树中
    68         }
    69         preOrder(T); //前序遍历
    70         printf("
    "); //输出空行
    71         inOrder(T); //中序遍历
    72         printf("
    ");
    73         postOrder(T); //后序遍历
    74         printf("
    ");
    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 <algorithm>
     2 #include <functional>
     3 #include <array>
     4 #include <iostream>
     5 #include <limits.h>
     6 #include <queue>
     7 #include <stdio.h>
     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 < T->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
  • 相关阅读:
    杭电1009 FatMouse' Trade
    【HDU 3183】 字符串处理
    quick_sort
    【 HDU 3172 Virtual Friends】 并查集+map指针优化
    【HDU 3127】 完全背包
    【URAL 1260】 DP (dfs打表之后找规律也行)
    【 HDU 3038 How Many Answers Are Wrong】 并查集好题
    腾讯云的图片上传与下载
    获取ip(局域网内的IP是一样的)
    vue表单提交之后,清空input里的数据
  • 原文地址:https://www.cnblogs.com/guxuanqing/p/6753089.html
Copyright © 2020-2023  润新知