数据结构

来源:互联网 发布:c语言从入门到精通怎样 编辑:程序博客网 时间:2024/06/06 07:48

1.栈的应用

题目1019:简单计算器

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:10439

解决:3824

题目描述:
    读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
输入:
    测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
输出:
    对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
样例输入:
1 + 24 + 2 * 5 - 7 / 110
样例输出:
3.0013.36
来源:
2006年浙江大学计算机及软件工程研究生机试真题

//读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。 #include <stdio.h>  #include<stack>  using namespace std;    int main()  {      stack<double> s;      char c1,c2;      int d;      //注意加一个空格对应数字之后的空格      while(scanf("%d ", &d)!=EOF && d!=0) {          s.push(d);          //%c %d%c 分别接受字符、字符后的空格、数字、字符。          //若判断最后一个字符不为空格,则说明输入结束          while( scanf("%c %d%c", &c1,&d,&c2)) {            if(c1 == '+') {              s.push(d);            }else if(c1 == '-'){              s.push(-d);            }else if(c1 == '*') {              double tmp = s.top() * d;              s.pop();              s.push(tmp);            }else if(c1 == '/') {              double tmp = double(s.top() / d);              s.pop();              s.push(tmp);            }                if(c2 != ' ') break;      //表达式输入结束          }            while(!s.empty()) {              if(s.size() == 1) {                  double r = s.top();                  s.pop();                  printf("%.2lf\n", r);              }else {                  double a,b,c;                  a = s.top();                  s.pop();                  b = s.top();                  s.pop();                  c = a + b;                  s.push(c);              }          }      }      return 0;  }  
题目1153:括号匹配问题

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:9756

解决:4243

题目描述:

    在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注.

输入:

    输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100。
    注意:cin.getline(str,100)最多只能输入99个字符!

输出:

    对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$","?"和空格组成,"$"和"?"表示与之对应的左括号和右括号不能匹配。

样例输入:
)(rttyy())sss)(
样例输出:
)(rttyy())sss)(?            ?$
来源:
2010年北京大学计算机研究生机试真题
#include <stdio.h> #include <stack> using namespace std; stack<int> S; //定义一个堆栈 char str[110]; //保存输入字符串 char ans[110]; //保存输出字符串 int main () { while (scanf ("%s",str)  != EOF) { //输入字符串    int i;    for (i = 0;str[i] != 0;i ++) { //从左到右遍历字符串     if (str[i] == '(') { //若遇到左括号 S.push(i); //将其数组下标放入堆栈中      ans[i] = ' '; //暂且将对应的输出字符串位置改为空格     }else if (str[i] == ')') { //若遇到右括号      if (S.empty() == false) { //若此时堆栈非空       S.pop(); //栈顶位置左括号与其匹配,从栈中弹出该已经匹配的左括号       ans[i] = ' '; //修改输出中该位置为空格      }             else ans[i] = '?'; //若堆栈为空,则无法找到左括号与其匹配,修改输出中该位置为?     }        else ans[i] = ' '; //若其为其它字符,与括号匹配无关,则修改输出为空格    }     while(!S.empty()) { //当字符串遍历完成后,尚留在堆栈中的左括号无法匹配     ans[ S.top() ] = '$'; //修改其在输出中的位置为$     S.pop(); //弹出    }    ans[i] = 0; //为了使输出形成字符串,在其最后一个字符后添加一个空字符    puts(str);  //输出原字符串    puts(ans); //输出答案字符串     } return 0; } 

2.哈夫曼树

题目1172:哈夫曼树

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:11259

解决:5125

题目描述:

哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。

输入:

输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。

输出:

输出权值。

样例输入:
5  1 2 2 5 9
样例输出:
37
来源:
2010年北京邮电大学计算机研究生机试真题
#include<stdio.h>#include<queue>using namespace std;priority_queue<int,vector<int>,greater<int> > Q;  //建立小顶堆 int main(){int n;while(scanf("%d",&n)!=EOF){while(Q.empty()==false)   //清空堆中元素 {Q.pop();}for(int i = 1; i <= n; i++)  //输入n个子叶的权值 {int x;scanf("%d",&x);Q.push(x); //将权值放入堆中 } int ans = 0;while(Q.size()>1){int a = Q.top();Q.pop();int b = Q.top();Q.pop(); ans += a  + b;Q.push(a+b);} printf("%d\n",ans);   //输出答案 } return 0;} 
题目1107:搬水果

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:8071

解决:3029

题目描述:

    在一个果园里,小明已经将所有的水果打了下来,并按水果的不同种类分成了若干堆,小明决定把所有的水果合成一堆。每一次合并,小明可以把两堆水果合并到一起,消耗的体力等于两堆水果的重量之和。当然经过 n‐1 次合并之后,就变成一堆了。小明在合并水果时总共消耗的体力等于每次合并所耗体力之和。

    假定每个水果重量都为 1,并且已知水果的种类数和每种水果的数目,你的任务是设计出合并的次序方案,使小明耗费的体力最少,并输出这个最小的体力耗费值。例如有 3 种水果,数目依次为 1,2,9。可以先将 1,2 堆合并,新堆数目为3,耗费体力为 3。然后将新堆与原先的第三堆合并得到新的堆,耗费体力为 12。所以小明总共耗费体力=3+12=15,可以证明 15 为最小的体力耗费值。

输入:

    每组数据输入包括两行,第一行是一个整数 n(1<=n<=10000),表示水果的种类数,如果 n 等于 0 表示输入结束,且不用处理。第二行包含 n 个整数,用空格分隔,第 i 个整数(1<=ai<=1000)是第 i 种水果的数目。

输出:

对于每组输入,输出一个整数并换行,这个值也就是最小的体力耗费值。输入数据保证这个值小于 2^31。

样例输入:
39 1 20
样例输出:
15
来源:
2011年吉林大学计算机研究生机试真题

#include<stdio.h>#include<queue>using namespace std;priority_queue<int,vector<int>,greater<int> > Q;  //建立小顶堆 int main(){int n;while(scanf("%d",&n)!=EOF&&n!=0){while(Q.empty()==false){Q.pop();}int a;for(int i = 0; i < n;  i++){scanf("%d",&a);Q.push(a);}int sum = 0;while(Q.size()>1){int a = Q.top();Q.pop();int b = Q.top();Q.pop();sum += a+b;Q.push(a+b); }printf("%d\n",sum);}}

3.二叉树

题目1078:二叉树遍历

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:7000

解决:4145

题目描述:

二叉树的前序、中序、后序遍历的定义:
前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树;
中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树;
后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。

输入:

两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C....最多26个结点。

输出:

输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。

样例输入:
ABCBACFDXEAGXDEFAG
样例输出:
BCAXEDGAF
来源:
2006年清华大学计算机研究生机试真题

#include<stdio.h>#include<string.h>struct Node{   //树结点结构体 Node *lchild;    //左儿子指针 Node *rchild;    //右儿子指针 char c; }Tree[50];  //静态内存分配数组 int  loc;  //静态数组中已经分配的节点个数 Node *creat()  //申请一个节点空间,返回指向其他的指针 {Tree[loc].lchild =  Tree[loc].rchild = NULL; //初始化左右儿子为空return &Tree[loc++]; } char str1[30], str2[30];void postOrder(Node *T)   //后序遍历 {if(T->lchild != NULL)   //若左子树不为空 {postOrder(T->lchild);   //递归遍历其右子树 }if(T->rchild != NULL){postOrder(T->rchild);}printf("%c",T->c);  //遍历该结点,输出字符信息  }   Node *build(int s1,int e1,int s2,int e2) { Node *ret = creat();  //为该树根节点申请空间ret -> c = str1[s1]; //该结点字符为前序遍历中第一个字符  int rootIdx;   for (int i = s2;i <= e2;i ++) //查找该根节点字符在中序遍历中的位置{    if (str2[i] == str1[s1]) {     rootIdx = i;     break;    }  }  if (rootIdx != s2) //若左子树不为空{     ret -> lchild = build(s1 + 1,s1 + (rootIdx - s2),s2,rootIdx - 1); //递归还原其左子树  }  if (rootIdx != e2) //若右子树不为空{     ret -> rchild = build(s1 + (rootIdx - s2) + 1,e1,rootIdx + 1,e2); //递归还原其右子树  }  return ret; //返回根节点指针 } int main () {  while (scanf ("%s",str1) != EOF) {    scanf ("%s",str2); //输入    loc = 0; //初始化静态内存空间中已经使用结点个数为0    int L1 = strlen(str1);    int L2 = strlen(str2); //计算两个字符串长度    Node *T = build(0,L1 - 1,0,L2 - 1); //还原整棵树,其根结点指针保存在T中    postOrder(T); //后序遍历    printf("\n"); //输出换行  }  return 0; } 
题目1184:二叉树遍历

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:4608

解决:1861

题目描述:

编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。
例如如下的先序遍历字符串:
ABC##DE#G##F###
其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。

输入:

输入包括1行字符串,长度不超过100。

输出:

可能有多组测试数据,对于每组数据,
输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。
每个输出结果占一行。

样例输入:
abc##de#g##f###
样例输出:
c b e g d f a 
来源:
2002年华中科技大学计算机研究生机试真题
#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>using namespace std;char str[101];int x; typedef struct node{    char c;    struct node *lchild, *rchild;}TNode, *Tree;//TNode* Creat(){//    if(str[x] == '#'){//        x++;//        return NULL;//    }//    TNode *T = new TNode;//    T->c = str[x++];//    T->lchild = Creat();//    T->rchild = Creat();//    return T;//}void Creat(Tree &T){    if(str[x] == '#'){        x++;        T = NULL;        return;    }    T = (TNode*)malloc(sizeof(TNode));//一定要开辟内存空间     T->c = str[x++];    T->lchild = NULL;    T->rchild = NULL;    Creat(T->lchild);    Creat(T->rchild);    return;}void print(Tree T){    if(T == NULL)        return;    print(T->lchild);    printf("%c ", T->c);    print(T->rchild);}int main(){    while(gets(str)){        x = 0;        Tree T;        //T = Creat();        Creat(T);        print(T);        printf("\n");    }    return 0;}

4.二叉排序树

题目1201:二叉排序树

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:8390

解决:3598

题目描述:

    输入一系列整数,建立二叉排序数,并进行前序,中序,后序遍历。

输入:

    输入第一行包括一个整数n(1<=n<=100)。
    接下来的一行包括n个整数。

输出:

    可能有多组测试数据,对于每组数据,将题目所给数据建立一个二叉排序树,并对二叉排序树进行前序、中序和后序遍历。
    每种遍历结果输出一行。每行最后一个数据之后有一个空格。

样例输入:
51 6 5 9 8
样例输出:
1 6 5 9 8 1 5 6 8 9 5 8 9 6 1 
提示:

输入中可能有重复元素,但是输出的二叉树遍历序列中重复元素不用输出。

来源:
2005年华中科技大学计算机保研机试真题
#include <stdio.h> #include <string.h> struct Node{ //二叉树结构体  Node *lchild; //左儿子指针  Node *rchild; //右儿子指针  int c;//保存数字 }Tree[110]; //静态数组 int loc; //静态数组中被使用元素个数 Node *creat() { //申请未使用的结点  Tree[loc].lchild = Tree[loc].rchild = NULL;  return &Tree[loc ++]; } void postOrder(Node *T) { //后序遍历  if (T -> lchild != NULL) {    postOrder(T -> lchild);  }  if (T -> rchild != NULL) {    postOrder(T -> rchild);  }  printf("%d ",T -> c); } void inOrder(Node *T) { //中序遍历  if (T -> lchild != NULL) {    inOrder(T -> lchild);  }  printf("%d ",T -> c);  if (T -> rchild != NULL){    inOrder(T -> rchild); } } void preOrder(Node *T) { //前序遍历  printf("%d ",T -> c);  if (T -> lchild != NULL) {    preOrder(T -> lchild);  }  if (T -> rchild != NULL) {    preOrder(T -> rchild);  } } Node *Insert(Node *T,int x) { //插入数字  if (T == NULL) { //若当前树为空    T = creat(); //建立结点    T -> c = x; //数字直接插入其根结点    return T; //返回根结点指针 } else if (x < T->c) //若x小于根结点数值    T -> lchild = Insert(T -> lchild,x); //插入到左子树上  else if (x > T->c) //若x大于根结点数值    T -> rchild = Insert(T -> rchild,x); //插入到右子树上.若根结点数值与x一样,根据题目要求直接忽略  return T; //返回根节点指针 } int main () {  int n;  while (scanf ("%d",&n) != EOF) {    loc = 0;    Node *T = NULL; //二叉排序树树根结点为空    for (int i = 0;i < n;i ++) { //依次输入n个数字     int x;     scanf ("%d",&x);     T = Insert(T,x); //插入到排序树中    }    preOrder(T); //前序遍历    printf("\n"); //输出空行    inOrder(T); //中序遍历    printf("\n");    postOrder(T); //后序遍历    printf("\n");  }  return 0; } 
题目1009:二叉搜索树

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:9842

解决:4331

题目描述:
判断两序列是否为同一二叉搜索树序列
输入:
开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束。
接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字,根据这个序列可以构造出一颗二叉搜索树。
接下去的n行有n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一颗二叉搜索树。
输出:

如果序列相同则输出YES,否则输出NO

样例输入:
25674325432675763420
样例输出:
YESNO
来源:
2010年浙江大学计算机及软件工程研究生机试真题
#include <stdio.h> #include <string.h> struct Node { //树节点结构体  Node *lchild;  Node *rchild;  int c; }Tree[110]; int loc; Node *creat() { //申请结点空间  Tree[loc].lchild = Tree[loc].rchild = NULL;  return &Tree[loc ++]; } char str1[25] , str2[25]; //保存二叉排序树的遍历结果,将每一棵树的前序遍历得到的字符串与中序遍历得到的字符串连接,得到遍历结果字符串 int size1 , size2; //保存在字符数组中的遍历得到字符个数 char *str; //当前正在保存字符串 int *size; //当前正在保存字符串中字符个数 void postOrder(Node *T) { //前序遍历  if (T -> lchild != NULL) {    postOrder(T -> lchild);  } if (T -> rchild != NULL) {    postOrder(T -> rchild); }  str[ (*size) ++ ] = T -> c + '0'; //将结点中的字符放入正在保存的字符串中 } void inOrder(Node *T) { //中序遍历  if (T -> lchild != NULL) {    inOrder(T -> lchild);  }  str[ (*size) ++ ] = T -> c + '0';  if (T -> rchild != NULL) {    inOrder(T -> rchild);  } } Node *Insert(Node *T,int x) { //将数字插入二叉树  if (T == NULL) {    T = creat();    T -> c = x;    return T;  }  else if (x < T->c)   T -> lchild = Insert(T -> lchild,x);  else if (x > T->c)    T -> rchild = Insert(T -> rchild,x);  return T; } int main () {  int n;  char tmp[12];  while (scanf ("%d",&n) != EOF && n != 0) {    loc = 0; //初始化静态空间为未使用    Node *T = NULL;    scanf ("%s",tmp); //输入字符串    for (int i = 0;tmp[i] != 0;i ++) {     T = Insert(T,tmp[i] - '0'); //按顺序将数字插入二叉排序树    }    size1 = 0; //保存在第一个字符串中的字符初始化为0    str = str1; //将正在保存字符串设定为第一个字符串    size = &size1; //将正在保存字符串中的字符个数指针指向size1    postOrder(T); //前序遍历    inOrder(T); //中序遍历    str1[ size1 ] = 0; //向第一个字符串的最后一个字符后添加空字符,方便使用字符串函数    while(n -- != 0) { //输入n个其它字符串     scanf ("%s",tmp); //输入     Node *T2 = NULL;     for (int i = 0;tmp[i] != 0;i ++) { //建立二叉排序树      T2 = Insert(T2,tmp[i] - '0');     }     size2 = 0; //第二个字符串保存字符初始化为0     str = str2; //将正在保存字符串设定为第二个字符串     size = &size2; //正在保存字符串中字符数量指针指向size2     postOrder(T2); //前序遍历 inOrder(T2); //中序遍历     str2[ size2 ] = 0; //字符串最后添加空字符     puts (strcmp(str1,str2) == 0 ? "YES" : "NO"); //比较两个遍历字符串,若相同则输出YES,否则输出NO    }  }  return 0; } 
原创粉丝点击