【数据结构】通讯录整理

问题描述

读取一组电话号码簿(由姓名和手机号码组成),将重复出现的项删除(姓名和电话号码都相同的项为重复项,只保留第一次出现的项),并对姓名相同手机号码不同的项进行如下整理:首次出现的项不作处理,第一次重复的姓名后面加英文下划线字符_和字母a,第二次重复的姓名后面加英文下划线字符_和字母b,依次类推。号码簿中姓名相同的项数最多不超过10个。最后对整理后的电话号码簿按照姓名从小到大进行排序。若输入没有指定排序算法,则只输出排序后的电话号码簿;若输入指定了快速排序算法,则按指定算法按排序键值先输出进行第一趟快速排序后的结果(即只输出姓名),然后输出排序后的电话号码簿。指定的快速排序算法如下:

辅助整型变量:
left : 当前参加排序的第一个元素在序列中的位置,初始值为0。
right: 当前参加排序的最后那个元素在序列中的位置, 初始值为n-1 。
i, j : 两个位置变量,初始值分别为left 与right+1。
选用left位置的元素作为分界元素,排序步骤:

  1. 反复执行动作i++,直到K[left]<=K[i]或者i=right。
    反复执行动作j–,直到K[left]>=K[j]或者j=left。
  2. 若i<j,则K[i]与K[j]交换位置,转到第1步。
  3. 若i>=j,则K[left]与K[j]交换位置,到此,分界元素K[s]的最终位置已经确定,然后对被K[left]分成的两部分中大小大于1的部分重复上述过程,直到排序结束。

输入形式

先从标准输入读取电话号码个数和排序算法要求(用0表示可以用任意的排序算法,1表示用指定的快速排序算法),两整数间以一个空格分隔,然后分行输入姓名和电话号码,姓名由不超过20个英文小写字母组成,电话号码由11位数字字符组成,姓名和电话号码之间以一个空格分隔,输入的姓名和电话号码项不超过100个。

输出形式

若指定了快速排序算法,则先输出第一趟快速排序后的结果:只在一行上输出第一趟排序后的姓名顺序,各姓名间以一个空格分隔。若未指定排序算法,则该行信息不输出。
无论是否指定排序算法,都要按照姓名从小到大的顺序分行输出最终的排序结果,先输出姓名再输出电话号码,中间以一个空格分隔。

样例1输入

15 0
liping 13512345678
zhaohong 13838929457
qiansan 13900223399
zhouhao 18578294857
anhai 13573948758
liping 13512345678
zhaohong 13588339922
liping 13833220099
boliang 15033778877
zhaohong 13838922222
tianyang 18987283746
sunnan 13599882764
zhaohong 13099228475
liushifeng 13874763899
caibiao 13923567890

样例1输出

anhai 13573948758
boliang 15033778877
caibiao 13923567890
liping 13512345678
liping_a 13833220099
liushifeng 13874763899
qiansan 13900223399
sunnan 13599882764
tianyang 18987283746
zhaohong 13838929457
zhaohong_a 13588339922
zhaohong_b 13838922222
zhaohong_c 13099228475
zhouhao 18578294857

样例1说明

输入了15个人名和电话号码,未指定排序算法。其中第一项和第六项完全相同,都是“liping 13512345678”,将第六项删除,第一项保留;
第八项和第一项人名相同,电话不同,则将第八项的人民整理为liping_a;同样,第二项、第七项、第十项、第十三项的人名都相同,将后面三项的人名分别整理为:zhaohong_a、zhaohong_b和zhaohong_c。
最后将整理后的电话簿按照姓名进行从小到大排序,分行输出排序结果。

样例2输入

15 1
liping 13512345678
zhaohong 13838929457
qiansan 13900223399
zhouhao 18578294857
anhai 13573948758
liping 13512345678
zhaohong 13588339922
liping 13833220099
boliang 15033778877
zhaohong 13838922222
tianyang 18987283746
sunnan 13599882764
zhaohong 13099228475
liushifeng 13874763899
caibiao 13923567890

样例2输出

anhai caibiao boliang liping zhouhao zhaohong_a liping_a qiansan zhaohong_b tianyang sunnan zhaohong_c liushifeng zhaohong
anhai 13573948758
boliang 15033778877
caibiao 13923567890
liping 13512345678
liping_a 13833220099
liushifeng 13874763899
qiansan 13900223399
sunnan 13599882764
tianyang 18987283746
zhaohong 13838929457
zhaohong_a 13588339922
zhaohong_b 13838922222
zhaohong_c 13099228475
zhouhao 18578294857

样例2说明

输入了15个人名和电话号码,指定用上述快速排序算法进行排序。对电话簿的整理与样例1完全相同。
按照指定快速排序算法对整理后的电话簿进行排序,第一趟排序的分界元素为第一个人名“liping”,第一趟结束后的顺序如上输出所示(只输出人名),最后输出排序后的结果。

代码

#include <iostream>
#include<cstring>
#include<vector>
using namespace std;

struct User {
    string name;
    string pho_num;
    User(string na, string pho) :name(na), pho_num(pho) {};
};

vector<User> CreatList(int n) {
    vector<User> list;
    list.reserve(20);
    vector<int> count;
    count.reserve(20);
    for (int i = 0; i < n; i++) {
        string name,pho_num;
        cin >> name >> pho_num;
        int count1 = 0;
        for (unsigned int j = 0; j < list.size(); j++) {
            if (name == list[j].name) {
                if (pho_num == list[j].pho_num) {
                    name = ""; break;
                }
                else {count1++;}
            }
        }
        if (name != "") {
            count.push_back(count1);
            User* user = new User(name, pho_num);
            list.push_back(*user);
            delete(user);
        }
    }
    list.shrink_to_fit();
    count.shrink_to_fit();
    for (unsigned int i = 0; i < count.size(); i++) {
        if (count[i] != 0) {
            string temp = "a";
                temp[0] += count[i] - 1;
                list[i].name += "_" + temp;
        }
    }
    vector<int>().swap(count);
    
    return list;
}

void Print_name(const vector<User> list, int n) {
    for (int i = 0; i <= n; i++) {
        cout << list[i].name<<" ";
    }
    cout <<endl;
}

void Print(const vector<User> list, int n) {
    for (int i = 0; i < n; i++) {
        cout << list[i].name <<" "<< list[i].pho_num << endl;
    }
}


void quickSort(vector<User> &list, int left, int right,int flag)
{

    if (left < right) {
        int i = left;
        int j = right + 1;
        list[left].name;
        while (true)
        {
            while (list[++i].name < list[left].name)
            { if (i == right) { break;} }
  
            while (list[--j].name > list[left].name)
            {if (j == left) { break;} }

            if (i >= j) break;
            /*����i,j��Ӧ��ֵ*/
            string temp = list[j].name;
            list[j].name = list[i].name;
            list[i].name = temp;
            temp = list[j].pho_num;
            list[j].pho_num = list[i].pho_num;
            list[i].pho_num = temp;
        }
        
        
        string temp = list[left].name;
        list[left].name = list[j].name;
        list[j].name = temp;
        temp = list[left].pho_num;
        list[left].pho_num = list[j].pho_num;
        list[j].pho_num = temp;
        if (flag == 1) Print_name(list, right);
        quickSort(list, left, j - 1, 0);
        quickSort(list, j + 1, right, 0);
    }
}


int main()
{
    int n,flag;
    cin >> n >> flag;
    vector<User> list = CreatList(n);
    n = list.size();
    quickSort(list, 0, n - 1, flag);
    Print(list, n);
    vector<User>().swap(list);
    return 0;
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值