王道机试指南数据结构二

例题10.1二叉树遍历(清华大学上机)

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
struct node{//定义结点
    char data;
    node* lchild;
    node* rchild;
    node(char(c)) : data(c), lchild(NULL), rchild(NULL){}//可以简化写法
};
node* create(int& pos, string str){//创建一课树
    char c = str[pos++];
    if(c == '#') return NULL;
    node* root = new node(c);//创建一个新的结点
    root->lchild = create(pos, str);//创建左子树 
    root->rchild = create(pos, str);//创建右子树 
    return root;//递归回溯之后,返回根一定是最开始 定义的第一个根节点 
}
void inorder(node* root){//都是通过根节点进行第一个访问 
    if(root == NULL) return;
    inorder(root->lchild);
    cout << root->data << " ";
    inorder(root->rchild);
}
int main(){
    string s;
    while(cin >> s){
        int pos = 0;
        node* root = create(pos, s);//定义一个node类型的名字叫root的指针 
        inorder(root);//进行中序遍历 
        cout << endl;
    }
    return 0;
}    

例题10.2二叉树的遍历(华中科技大学上机)

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
char pre[28], in[28];
void post(int root, int start, int end){//root为前序中当前根节点的下标
    if(start > end) return;//表示递归出口 
    int i = start;//i表示当前的根在中序的位置,从start开始找 
    while(i < end && in[i] != pre[root]) i++;//找到先序的根在中序遍历的位置
    post(root + 1, start, i - 1);//相当于从前序中依次遍历
    post(root + 1 + i - start, i + 1, end);
    cout << pre[root];
}
int main(){
    string pres, ins;
    int n;
    while(cin >> pres >> ins){
        n = pres.size();//n为用例的长度 
        for(int i = 0; i < n; i++) pre[i] = pres[i];//将字符转换为char类型的数组来存储 
        for(int i = 0; i < n; i++) in[i] = ins[i];
        post(0, 0, n - 1); //end为下标,所以应该从n - 1开始 
        cout << endl; 
    }
    return 0;
}  

例题10.3二叉排序树(华中科技大学上机)

 #include<iostream>
#include<cstdio>
using namespace std;
struct TreeNode{
    int data;
    TreeNode *lchild;
    TreeNode *rchild; 
    TreeNode(int x) : data(x), lchild(NULL), rchild(NULL){}
};
void insert(TreeNode* &root, int x, int pre){
    if(root == NULL){
        root = new TreeNode(x);//返回的是上一层的root->child 
        cout << pre << endl;
        return;
    }else if(x < root->data){
        insert(root->lchild, x, root->data);
    }else insert(root->rchild, x, root->data);
}
int main(){
    int n, x;
    while(cin >> n){
        TreeNode *root = NULL;
        for(int i = 0; i < n; i++){
            cin >> x;
            insert(root, x, -1);
        }
    }
    return 0;
}  

例题10.4 二叉排序树(华中科技上机)

#include<iostream>
#include<cstdio>
#include<string.h>
#include<map>
using namespace std;
map<int, int> flag;
struct node{
    int data;
    node* lchild;
    node* rchild;
    node(int x) : data(x), lchild(NULL), rchild(NULL){}
};
void create(node* &root, int x){
    if(root == NULL){
        root = new node(x);
        return;
    }
    if(x < root->data) create(root->lchild, x);
    else create(root->rchild, x);
}
void preorder(node* root){
    if(root == NULL) return;
    cout << root->data << " ";
    preorder(root->lchild);
    preorder(root->rchild);
}
void inorder(node* root){
    if(root == NULL) return;
    inorder(root->lchild);
    cout << root->data << " ";
    inorder(root->rchild);
}
void postorder(node* root){
    if(root == NULL) return;
    postorder(root->lchild);
    postorder(root->rchild);
    cout << root->data << " ";
}
int main(){
    int n, x;
    while(cin >> n){
        node* root = NULL;
        for(int i = 0; i < n ;i++){
            cin >> x;
            if(flag[x] != 1){
                flag[x] = 1;
                create(root, x);
            } 
        }
        flag.clear();
        preorder(root);
        cout << endl;
        flag.clear();
        inorder(root);
        cout << endl;
        flag.clear();
        postorder(root);
        cout << endl;
    }
    return 0;
}

习题10.1二叉搜索树(浙江大学复试上机)

#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
using namespace std;
vector<int> pre, in, pretest, intest;
struct node{//定义树的结点
    int data;
    node* lchild;
    node* rchild;
    node(int x) : data(x), lchild(NULL), rchild(NULL){}
};
void insert(node* &root, int x){//用插入法创建一棵树
    if(root == NULL){
        root = new node(x);
        return;
    }
    if(x > root->data) insert(root->rchild, x);
    else insert(root->lchild, x);
}
void preorder(node* root, vector<int> &a){//先序遍历的序列输入到容器a,注意容器用引用 
    if(root == NULL) return;
    a.push_back(root->data);
    preorder(root->lchild, a);
    preorder(root->rchild, a);
}
void inorder(node* root, vector<int> &a){//中序遍历的序列输入到容器a
    if(root == NULL) return;
    inorder(root->lchild, a);
    a.push_back(root->data);
    inorder(root->rchild, a);
}
bool judge(vector<int> a, vector<int> b){//判断容器内元素是否相同
    for(int i = 0; i < a.size(); i++){
        if(a[i] != b[i]) return false;
    }
    return true;
}
int main(){
    int n;
    string str;
    while(cin >> n && n != 0){//注意这种输入的方法
        cin >> str;
        node* root = NULL;
        for(int i = 0; i < str.size(); i++){
            insert(root, str[i] - '0');
        }
        preorder(root, pre);//进行前序遍历,将结果存入
        inorder(root, in);//进行中序遍历,将结果存入
        for(int i = 0; i < n; i++){//进行n次的循环 
            pretest.clear();//将用于存前序序列的容器清空
            intest.clear();//将用于存中序序列的容器清空
            string temp;//设置一个临时temp,用来接收输入的字符串
            cin >> temp;
            node* roottest = NULL;//定义一个空树
            for(int j = 0; j < temp.size(); j++){//字符串变成整型,插入法建树
                insert(roottest, temp[j] - '0');
            }
            preorder(roottest, pretest);//前序遍历结果存入pretest 
            inorder(roottest, intest);//中序遍历结果存入intest 
            if(judge(pre, pretest) && judge(in, intest)) cout <<"YES"<<endl;//判断并且输出
            else cout << "NO" << endl;
        }
    }
    return 0;
}    

例题10.5 复数集合(北京邮电大学)

#include<cstdio>
#include<iostream>
#include<string>
#include<queue>
using namespace std;
struct complex{
    int real, imag;
    complex(int a, int b) : real(a), imag(b){}
    friend bool operator < (complex c1, complex c2){
        if(c1.imag*c1.imag + c1.real*c1.real== c2.imag*c2.imag + c2.real*c2.real){
            return c1.real < c2.real;
        }else{
            return c1.imag*c1.imag + c1.real*c1.real < c2.imag*c2.imag + c2.real*c2.real;
        }
    }
};
int main(){
    int n;
    string str;
    while(cin >> n){
        priority_queue<complex> q;
        for(int i = 0; i < n; i++){
            cin >> str;
            if(str == "Pop"){
                if(!q.empty()){
                    cout << q.top().real <<"+i" << q.top().imag << endl;
                    q.pop();
                    cout << "SIZE = " << q.size() << endl; 
                }else cout << "empty" << endl;
            }else if(str == "Insert"){
                int ta, tb;
                scanf("%d+i%d", &ta, &tb);
                q.push(complex(ta, tb));
                cout << "SIZE = " << q.size() << endl;
            } 
        }   
    }
    return 0;
}    

例题10.6 哈夫曼树(北京邮电大学)

#include<iostream>
#include<queue>
using namespace std;
int main(){
    int n;
    while(cin >> n){
        priority_queue<int, vector<int>, greater<int> > q;
        int ans = 0;
        for(int i = 0; i < n; i++){
            int temp;
            cin >> temp;
            q.push(temp);
        }
        while(q.size() > 1){
            int x = q.top();
            q.pop();
            int y = q.top();
            q.pop();
            q.push(x + y);
            ans += x + y;
        }
        cout << ans << endl;
    }
    return 0;
}    

习题10.2 查找第K小的数(北京邮电大学上机)

#include<iostream>
#include<cstdio>
#include<queue>
#include<map>
using namespace std;
int main(){
    int n, k;
    while(cin >> n){
        map<int, int> flag;
        priority_queue<int, vector<int>, greater<int> > q;
        for(int i = 0; i < n; i++){
            int temp; 
            cin >> temp;
            if(flag[temp] != 1){
                flag[temp] = 1;
                q.push(temp);
            }
        }
        cin >> k;
        for(int i = 0 ; i < k - 1; i++){
            q.pop();
        }
        cout << q.top() << endl;
    }
}   

习题10.3 搬水果(吉林大学上机)

#include<iostream>
#include<cstdio>
#include<queue>
#include<map>
using namespace std;
int main(){
    int n, k;
    while(cin >> n){
        map<int, int> flag;
        priority_queue<int, vector<int>, greater<int> > q;
        for(int i = 0; i < n; i++){
            int temp; 
            cin >> temp;
            if(flag[temp] != 1){
                flag[temp] = 1;
                q.push(temp);
            }
        }
        cin >> k;
        for(int i = 0 ; i < k - 1; i++){
            q.pop();
        }
        cout << q.top() << endl;
    }
}  

例题10.7查找学生信息

#include<iostream>
#include<cstdio>
#include<string>
#include<map>
using namespace std;
struct inf{
    string name, sex;
    int age;
};
int main(){
    int n, m;
    map<string, inf> mp;//建立学号和信息之间的映射
    cin >> n;
    for(int  i = 0; i < n; i++){
        string num, name, sex;
        int age;
        cin >> num >> name >> sex >> age;
        mp[num].name = name;
        mp[num].sex = sex;
        mp[num].age = age;
    }
    cin >> m;
     while(m > 0){
         m--;
         string tempnum;
         cin >> tempnum;
         if(mp[tempnum].name == "") cout << "No Answer!" << endl;
         else cout << tempnum << " " << mp[tempnum].name << " " << mp[tempnum].sex << " " << mp[tempnum].age << " "<< endl;
     }
    return 0;
}  

例题10.8 魔咒词典(浙江大学)

#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(){
    string s, s1, s2;
    map<string, string> mp0;
    map<string, string> mp1;
    while(getline(cin, s) && s != "@END@"){
        auto it = s.find(']');
        s1 = s.substr(0, it+1);
        s2 = s.substr(it + 2, s.size() - s1.size() - 1);
        mp0[s1] = s2;
        mp1[s2] = s1;
    }
    int n;
    cin >> n;
    getchar();
    for(int i = 0; i < n; i++){
        string temp;
        getline(cin, temp); 
        if(mp0[temp] != "") cout << mp0[temp] << endl;
        else if(mp1[temp] != ""){//去掉 【  】
            string s00;
            s00 = mp1[temp].substr(1, mp1[temp].size() - 2);
            cout << s00 << endl;
        }
        else cout << "what?" << endl;
    }
    return 0;
}    

例题10.9子串计算(北京大学复试上机)

注意这里面如何截取一个字符串的所有子串

#include<iostream>
#include<cstdio>
#include<string>
#include<map>
using namespace std;
int main(){
    string str;
    while(cin >> str){
        map<string, int> mp;
        for(int i = 0; i <= str.size(); i++){
            for(int j = 0; j < i; j++){
                string s = str.substr(j, i - j);
                mp[s]++;
            }
        }
        for(auto it = mp.begin(); it != mp.end(); it++){
            if(it->second > 1) cout << it->first << " " << it->second << endl;
        }
    }
    return 0;
}    
 

习题10.4 统计同成绩的学生(浙江大学上机)

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
int main(){
    int n;
    while(cin >> n && n != 0){
        map<int, int> mp;
        for(int i = 0; i < n; i++){
            int temp;
            cin >> temp;
            mp[temp]++;
        }
        int testnum;
        cin >> testnum;
        cout << mp[testnum] << endl;
    }
}     

习题10.5 开门人和关门人

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int toSecond(int hour, int min, int sec){
    return hour * 3600 + min * 60 + sec;
}
int main(){
    int n, opentime = 24*3600, closetime = 0;
    string tempnum, opennum, closenum;
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> tempnum;
        int hour, min, sec;
        scanf("%d:%d:%d", &hour, &min, &sec);
        if(toSecond(hour, min, sec) < opentime){
            opennum = tempnum;
            opentime = toSecond(hour, min, sec);
        }
        scanf("%d:%d:%d", &hour, &min, &sec);
        if( toSecond(hour, min, sec) > closetime){
            closenum = tempnum;
            closetime = toSecond(hour, min, sec);
        }
    }
    cout << opennum << " " << closenum << endl;
    return 0;
}    

习题10.6 谁是你潜在的朋友(北京大学复试上机)

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
int main(){
    int n, m;
    cin >> n >> m;
    map<int, int> book;//用于记录i号书的读者数
    int reader[201];
    for(int i = 0; i < n; i++){
        int temp;
        cin >> temp;
        book[temp]++;
        reader[i] = temp;
    }
    for(int i = 0; i < n; i++){
        if(book[reader[i]] > 1) cout << book[reader[i]] - 1 << endl;
        else cout << "BeiJu" << endl;
    }
}