算法笔记系列:4.1 排序 4.2 散列

4.1.1 选择排序

简单选择排序原理:每次都找出区间中最小的元素,并与区间第一个元素进行交换,不断缩小区间最终完成排序,时间复杂度O(n^2)

4.1.2 插入排序

直接插入排序原理:将后面的每一个元素依次插入前面的有序部分,最终整个序列有序

4.1.3 排序题与sort函数的应用

  • 考试中一般使用C++中的sort函数进行编写

  • sort使用必须加上头文件 #include和 using namespace std

sort(首元素地址(必填),尾元素地址的下一个地址(必填),比较函数(选填));
  • sort中的cmp比较函数:只要记住<号就是从小到大,>就是从大到小

【PAT A1025】PAT Ranking

思路:难点在于每个考场的排序怎么排,就是每一次输入一个考场学生的信息后,在这一考场的所有学生先进行排序,按排序输入考场排名

# include<cstdio>
# include<algorithm>
# include<cstring>
using namespace std;

struct Student
{
    char register_num[15];
    int final_rank;
    int location_num;
    int local_rank;
    int score;
}stu[30010];

bool cmp(Student a,Student b){
    if (a.score!=b.score) return a.score>b.score;
    else return strcmp(a.register_num,b.register_num)<0;
}
int main(){
    int N,K,total=0;
    scanf("%d",&N);
    for (int i=1;i<=N;i++){
        scanf("%d",&K);
        for (int n=0;n<=K-1;n++){
            stu[n+total].location_num=i;
            scanf("%s %d",&stu[n+total].register_num,&stu[n+total].score);
        }
        sort(stu+total,stu+total+K,cmp);
        stu[total].local_rank=1;
        for (int m=1;m<=K-1;m++){
            if (stu[m+total].score==stu[m+total-1].score) stu[m+total].local_rank=stu[m+total-1].local_rank;
            else stu[m+total].local_rank=m+1;
        }
        total+=K;
    }
    sort(stu,stu+total,cmp);
    stu[0].final_rank=1;
    for (int i=1;i<=total-1;i++){
            if (stu[i].score==stu[i-1].score) stu[i].final_rank=stu[i-1].final_rank;
            else stu[i].final_rank=i+1;
    }
    printf("%d\n",total);
    for (int n=1;n<=total;n++){
        printf("%s %d %d %d\n",stu[n-1].register_num,stu[n-1].final_rank,stu[n-1].location_num,stu[n-1].local_rank);
    }
    return 0;
}

4.2.1 散列的定义与整数散列

思想:直接把输入的数作为数组的下标来对这个数的性质进行统计

散列(hash) 将元素通过一个函数转换为整数,使得该整数可以尽量唯一的代表这个元素

当这个元素key本身就是整数时,常用的散列函数有直接地址法,除留余数法

除留余数法:注意表长Tsize必须不小于mod
H ( k e y ) = k e y % m o d H(key)=key\%mod H(key)=key%mod
因此会出现不同的key值,H(key)一样的情况,为了解决这种冲突,常用的三种方法

  • 线性探查法: 发现占用,就H(key)+1寻找,到表位就转到表头,不断挨个找直到找到

  • 平方探查法:针对上面方法容易扎堆的错开寻找办法,寻找顺序为 H ( k e y ) + 1 2 、 H ( k e y ) − 1 2 、 H ( k e y ) + 2 2 、 H ( k e y ) − 2 2 H(key)+1^2、H(key)-1^2、H(key)+2^2、H(key)-2^2 H(key)+12H(key)12H(key)+22H(key)22

  • 链地址法:不计算新的hash值,而是把所有H(key)相同的key连接成一条单链表

一般来说用标准库中的map函数来直接使用hash功能,C++11以后可以用unordered_map更快

4.2.2 字符串hash初步

当key不是整数时,设计散列函数,这里举例当key是字符串时,映射为26进制(都是大写字符),52进制(大小写都有)

例题:给出N个字符串(恰好三位大写字符串),再给出M个查询字符串,问每个查询字符串在N个字符串中出现的次数

# include<cstdio>
int hashTable[26*26*26+10]={0};
char s[10000][5],temp[5];
int hashfunc(char s[],int len){
    int key=0;
    for (int i=0;i<len;i++){
        key=key*26+(s[i]-'A');
    }
    return key;
}
int main(){
    int N,M;
    scanf("%d%d",&N,&M);
    for (int i=0;i<N;i++){
        scanf("%s",s[i]);
        int id=hashfunc(s[i],3);
        hashTable[id]++;
    }
    for (int i=0;i<M;i++){
        scanf("%s",temp);
        int id=hashfunc(temp,3);
        printf("%d\n",hashTable[i]);
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值