Hash算法,插入排序,希尔排序,选择排序,冒泡排序,归并排序,快速排序,堆排序,基数排序

news2024/11/29 0:53:07

Hash算法

hash就是散列表,就是把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。

实质就是压缩映射,散列值的空间通常远小于输入的空间。

常利用hash算法,将输入的一千万个检索串转化为题目中所说大约三百万个不同的数,进行排序选出我们需要的值即可。

出现冲突时,可以用拉链法,就是用链表来解决冲突,用一个链表数组,来存储相应数据,当出现冲突时,依次添加到链表的后面进行处理。

例题1 正方形

基本思路就是,将输入的点存在数组和哈希表中,数组是为了顺序遍历,哈希表是为了查找快。

取正方形对角线上的两个顶点,根据几何关系计算另外一条对角线上。两个顶点,如果计算出的另外两个顶点都在map中,则找到一个正方形。

要注意的是,因为两条对角线各被计算了一次,所以结果要除以2。

已经知道对角线AC上的a,c坐标,求b点坐标的公式为:

bx=(ax+cx+cy-ay)/2;

by=(ay+cy+ax-cx)/2;

代码实现:

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
const int H = 10007;
int ptx[N], pty[N], hashTable[H];
int cur, n;
long ans;
struct Node {
    int x;
    int y;
    int next;
}node[N];
void initHash() {
    for (int i = 0; i < H; i++) {
        hashTable[i] = -1;
    }
    cur = ans = 0;
}
void insertHash(int x, int y) {
    int h = (x * x + y * y) % H;//哈希函数
    node[cur].x = x;
    node[cur].y = y;
    node[cur].next = hashTable[h];
    hashTable[h] = cur++;
}
bool searchHash(int x, int y) {
    int h = (x * x + y * y) % H;
    int next = hashTable[h];
    while (next != -1) {
        if (x == node[next].x && y == node[next].y)
            return true;
        next = node[next].next;
    }
    return false;
}
int main() {
    iostream::sync_with_stdio(false);
    while (cin >> n && n != 0) {
        initHash();
        for (int i = 0; i < n; i++) {
            cin >> ptx[i] >> pty[i];
            insertHash(ptx[i], pty[i]);
        }
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int x1 = ptx[i] - (pty[i] - pty[j]);
                int y1 = pty[i] + (ptx[i] - ptx[j]);
                int x2 = ptx[j] - (pty[i] - pty[j]);
                int y2 = pty[j] + (ptx[i] - ptx[j]);
                if (searchHash(x1, y1) && searchHash(x2, y2))
                    ans++;
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int x1 = ptx[i] - (pty[i] - pty[j]);
                int y1 = pty[i] + (ptx[i] - ptx[j]);
                int x2 = ptx[j] - (pty[i] - pty[j]);
                int y2 = pty[j] + (ptx[i] - ptx[j]);
                if (searchHash(x1, y1) && searchHash(x2, y2))
                    ans++;
            }
        }
        ans >>= 2;
        cout << ans << endl;
    }

    return 0;
}

例题2 字符串哈希

双重哈希,没用拉链法

代码实现:

#include<bits/stdc++.h>
using namespace std;
void read(int& x) {
    x = 0;
    int f = 0;
    char ch = getchar();
    while (ch < '0' || ch>'9') {
        f |= (ch == '-');
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    x = f ? -x : x;
    return;
}
const int maxn = 200020;
const int mod = 998244353;
const int p = 1e9 + 7;
int ans, n, cnt;
char str[maxn];
struct node {
    unsigned long long res, ress;
    unsigned long long hash(char* s, int len) {
        unsigned long long Ans = 0;
        for (int i = 1; i <= len; i++) {
            Ans = Ans * mod + s[i];
        }
        return Ans;
    }
    unsigned long long rehash(char* s, int len) {
        unsigned long long Ans = 0;
        for (int i = 1; i <= len; i++) {
            Ans = Ans * p + s[i];
        }
        return Ans;
    }
    bool operator<(const node& x) {
        return res == x.res ? ress < x.ress : res < x.res;
    }
}st[maxn];
int main() {
    iostream::sync_with_stdio(false);
    read(n);
    for (int i = 1; i <= n; i++) {
        cin >> str + 1;
        int len = strlen(str + 1);
        st[++cnt].res = st[i].hash(str + 1, len);
        st[++cnt].ress = st[i].rehash(str + 1, len);
    }
    sort(st + 1, st + 1 + cnt);
    for (int i = 1; i <= n; i++) {
        if (st[i].res == st[i + 1].res)
            if (st[i].ress == st[i + 1].ress)
                ans++;
    }
    cout << n - ans << endl;
    return 0;
}

插入排序

原理:将原数列中的第一个元素视为一个有序数列,视第二个元素至最后一个元素为未排序元素。从头到尾扫描整个未排序数列,然后将扫描到的每个元素插入到有序序列中的适当位置。

复杂度:最好可以达到O(n),最坏是O(n2),平均O(n2)

#include<bits/stdc++.h>
using namespace std;
int main() {
    //全都是从小到大
    iostream::sync_with_stdio(false);
    int n;
    cin >> n;
    int* arr = new int[n];
    for (int i = 0; i < n; i++)cin >> arr[i];
    for (int i = 1; i < n; i++) {
        int temp = arr[i];
        int j;
        for (j = i - 1; j >= 0 && temp < arr[j]; j--)
            arr[j + 1] = arr[j];
        arr[j + 1] = temp;
    }
    for (int i = 0; i < n; i++) {
        cout << arr[i] << " ";
    }

    delete[]arr;
    return 0;
}

希尔排序

原理:选择一个增量序列,按照增量序列元素个数进行多次排序,每次排序根据对应的增量将待排序的数列分成若干个长度为m的子序列,分别对子表进行插入排序,当增量为1的时候,整个序列作为一个表来处理,表长度就是整个序列的长度。

复杂度:最好可以达到O(n1.3),最坏是O(n2),平均O(nlog2n)~O(n2)

#include<bits/stdc++.h>
using namespace std;
int main() {
    //全都是从小到大
    iostream::sync_with_stdio(false);
    int n;
    cin >> n;
    int* arr = new int[n];
    for (int i = 0; i < n; i++)cin >> arr[i];
    for (int d = n / 2; d >= 1; d /= 2) {
        for (int i = d; i < n; i++) {
            int temp = arr[i];
            int j;
            for (j = i - d; j >= 0 && temp < arr[j]; j = j - d)
                arr[j + d] = arr[j];
            arr[j + d] = temp;
        }
    }
    for (int i = 0; i < n; i++) {
        cout << arr[i] << " ";
    }

    delete[]arr;
    return 0;
}

选择排序

复杂度:O(n2)

#include<bits/stdc++.h>
using namespace std;
int main() {
    //全都是从小到大
    iostream::sync_with_stdio(false);
    int n;
    cin >> n;
    int* arr = new int[n];
    for (int i = 0; i < n; i++)cin >> arr[i];
    for (int i = 0; i < n - 1; i++) {
        int flag = i;
        for (int j = i + 1; j < n; j++)
            if (arr[flag] > arr[j]) flag = j;//选取最小值的下标
        if (flag != i) swap(arr[flag], arr[i]);
    }
    for (int i = 0; i < n; i++) {
        cout << arr[i] << " ";
    }

    delete[]arr;
    return 0;
}

冒泡排序

复杂度:最好可以达到O(n),最坏是O(n2),平均O(n2)

#include<bits/stdc++.h>
using namespace std;
int main() {
    //全都是从小到大
    iostream::sync_with_stdio(false);
    int n;
    cin >> n;
    int* arr = new int[n];
    for (int i = 0; i < n; i++)cin >> arr[i];
    for (int i = 0; i < n; i++) {
        int flag = 0;
        for (int j = 0; j < n - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(arr[j], arr[j + 1]);
                flag = 1;
            }
        }
        if (flag == 0)break;
    }
    for (int i = 0; i < n; i++) {
        cout << arr[i] << " ";
    }
    delete[]arr;
    return 0;
}

归并排序(递归实现)

复杂度:O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
int datas[10];
void Merge(int first1, int last1, int last2) {
    int* temp = new int[10];
    int i = first1, j = last1 + 1, k = first1;
    while (i <=last1 && j <= last2) {
        if (datas[i] <= datas[j])temp[k++] = datas[i++];
        else temp[k++] = datas[j++];
    }
    while (i <= last1)temp[k++] = datas[i++];
    while (j <= last2)temp[k++] = datas[j++];
    for (i = first1; i <= last2; i++)datas[i] = temp[i];
    delete[]temp;
}
void MergeSort1(int first, int last) {
    if (first == last)return;
    else {
        int mid = (first + last) / 2;
        MergeSort1(first, mid);
        MergeSort1(mid + 1, last);
        Merge(first, mid, last);
    }
}
int main() {
    //全都是从小到大
    iostream::sync_with_stdio(false);
    for (int i = 0; i < 10; i++) {
        cin >> datas[i];
    }
    MergeSort1(0,9);
    for (int i = 0; i < 10; i++) {
        cout << datas[i] << " ";
    }
    return 0;
}

归并排序(非递归实现)

#include<bits/stdc++.h>
using namespace std;
int datas[10];
int length = 10;
void Merge(int first1, int last1, int last2) {
    int* temp = new int[10];
    int i = first1, j = last1 + 1, k = first1;
    while (i <= last1 && j <= last2) {
        if (datas[i] <= datas[j])temp[k++] = datas[i++];
        else temp[k++] = datas[j++];
    }
    while (i <= last1)temp[k++] = datas[i++];
    while (j <= last2)temp[k++] = datas[j++];
    for (i = first1; i <= last2; i++)datas[i] = temp[i];
    delete[]temp;
}
void MergePass(int h) {
    int i = 0;
    while (i + 2 * h <= length) {
        Merge(i, i + h - 1, i + 2 * h - 1);
        i = i + 2 * h;
    }
    if (i + h < length) {
        Merge(i, i + h - 1, length - 1);
    }
}
void MergeSort2() {
    int h = 1;
    while (h < length) {
        MergePass(h);
        h = 2 * h;
    }
}

int main() {
    //全都是从小到大
    iostream::sync_with_stdio(false);
    for (int i = 0; i < 10; i++) {
        cin >> datas[i];
    }
    MergeSort2();
    for (int i = 0; i < 10; i++) {
        cout << datas[i] << " ";
    }
    return 0;
}

快速排序

复杂度:最好可以达到O(nlog2n),最坏是O(n2),平均O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
int datas[10];
int Partition(int first, int last) {
    int i = first, j = last;
    while (i < j) {
        while (i < j && datas[i] <= datas[j])j--;//右侧扫描
        if (i < j) {
            swap(datas[i], datas[j]);
            i++;
        }
        while (i < j && datas[i] <= datas[j])i++;//左侧扫描
        if (i < j) {
            swap(datas[i], datas[j]);
            j--;
        }

    }
    return i;
}
void QuickSort(int first, int last) {
    if (first >= last)return;//区间长度为1,递归结束
    else {
        int pivot = Partition(first, last);
        QuickSort(first, pivot-1);//对左侧子序列进行快速排序
        QuickSort(pivot + 1, last);//对右侧子序列进行快速排序

    }
}
int main() {
    //全都是从小到大
    iostream::sync_with_stdio(false);
    for (int i = 0; i < 10; i++) {
        cin >> datas[i];
    }
    QuickSort(0, 9);
    for (int i = 0; i < 10; i++) {
        cout << datas[i] << " ";
    }
    return 0;
}

基数排序

假设待排序序列记录看成是由d个子关键码复合而成,每个子关键码的取值范围为m个。

每一趟分配的时间复杂度是O(n),每一趟收集的时间复杂度为O(m),整个排序需要执行d趟。

复杂度:O(d(n+m)

#include<bits/stdc++.h>
using namespace std;
struct Node {
    int data;
    Node* next;
};
void RadixSort(Node* first, int d) {
    Node* front[10], * rear[10], * tail;
    int i, j, k, base = 1;
    for (i = 1; i <= d; i++) {
        for (j = 0; j < 10; j++) {
            front[j] = rear[j] = NULL;
        }
        while (first != NULL) {
            k = (first->data / base) % 10;
            if (front[k] == NULL)front[k] = rear[k] = first;
            else rear[k] = rear[k]->next = first;
            first = first->next;
        }
        for (j = 0; j < 10; j++) {
            if (front[j] == NULL)continue;
            if (first == NULL)first = front[j];
            else tail->next = front[j];
            tail = rear[j];
        }
        tail->next = NULL;
        base = base * 10;
    }
}
int main() {
    iostream::sync_with_stdio(false);
    return 0;
}

堆排序

复杂度:O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
int datas[10];
int length = 10;
void Sift(int k, int last) {
    int i, j;
    i = k; j = 2 * i + 1;//i是被调整结点,j是i的左孩子
    while (j <= last) {
        if (j < last && datas[j] < datas[j + 1])j++;//j指向左右孩子的较大者
        if (datas[i] > datas[j])break;//已经是堆
        else {
            swap(datas[i], datas[j]);
            i = j; j = 2 * i + 1;//被调整结点位于结点j的位置
        }
    }
}
void HeapSort() {
    int i;
    for (i = length / 2 - 1; i >= 0; i--) {
        Sift(i, length - 1);
    }
    for (i = 1; i < length; i++) {
        swap(datas[0], datas[length - i]);
        Sift(0, length - i - 1);//重建堆
    }
}
int main() {
    //全都是从小到大
    iostream::sync_with_stdio(false);
    for (int i = 0; i < 10; i++) {
        cin >> datas[i];
    }
    HeapSort();
    for (int i = 0; i < 10; i++) {
        cout << datas[i] << " ";
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/166335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Linux Shell脚本攻略》学习笔记-第七章

7.1 简介 随着磁盘存储技术的发展&#xff0c;最简单地备份方法是添加新的磁盘设备或是使用云存储&#xff0c;而不再是依赖磁盘。 但是也需要压缩备份数据&#xff0c;降低存储空间需求以及传输时间。把数据存放在云端之前应该对其加密。数据在加密之前通常都要先进行归档和压…

2.2总线的性能指标

文章目录一、总线传输周期二、总线时钟周期三、总线工作频率四、总线时钟频率五、总线宽度六、总线带宽1.概念2.注意点3.案例分析4.总结补充七、总线复用八、信号线数九、总结这一节我们一起学习评价 总线性能的指标&#xff0c;这些指标很可能在选择题或者大题第一小题出现。一…

Git团队协作及分支策略

目录 分布式版本控制系统 访问模型 分支策略-Git flow feature 分支策略-Github flow 分支策略-Gitlab flow 主干开发模式 总结 分布式版本控制系统 分布式相比于集中式的最大区别在于开发者可以提交到本地&#xff0c;每个开发者通过克隆&#xff08;git clone&#…

Pytest参数化-下篇

&#x1f60e;&#x1f60e;原文出自&#xff1a;测个der&#xff0c;博主的公众号&#xff0c;格式美观一些。 关于参数化的其他案例 数据嵌套及多参数传参 import pytestpwd_datas [["QINGAN",{"user":"SHIER","pwd":"1234…

5个关键词回顾2022年个推技术实践

作为一家数据智能服务商&#xff0c;2022年每日互动&#xff08;个推&#xff09;在为开发者和行业客户提供优质服务的同时&#xff0c;不断砥砺创新&#xff0c;追逐技术前沿。个推还持续参与开发者生态建设&#xff0c;积极总结、分享自身技术实战经验&#xff0c;面向行业输…

该如何测客户端专项测试?

整个行业现在越来越重视客户端的专项测试了。像接口的性能测试、webview 测试、H5性能分析等&#xff0c;每一项都需要测试。而对于卡顿的分析、系统资源分析、耗电量测试及弱网测试这块&#xff0c;也变得越来越重要了&#xff01;后面也会有相关的文章更新。大家可以戳此关注…

快解析远程访问解决方案——安全稳定,部署简单

我们说的远程办公通常指狭义上的远程办公&#xff0c;是指通过远程技术&#xff0c;或远程控制软件&#xff0c;对远程电脑进行操作办公&#xff0c;实现非本地办公&#xff0c;如在家办公、异地办公、移动办公等远程办公模式。这种技术的关键在于:穿透内网和远程控制的安全性。…

Wisej.NET 3.1.6 Crack

新功能 Wisej.NET 3.1 通过添加几个新的独特功能和简化的安装过程增强了里程碑 3.0 版本。 除了大量错误修复和对我们库的显着性能增强之外&#xff0c;3.1 还包括以下值得注意的新功能&#xff1a; 视觉工作室市场 Wisej.NET 现在比以往任何时候都更容易使用。或 Visual Studi…

联合证券|五大国际巨鳄集体爆雷,美股期指大跳水!

商场现已进入到雷雨季&#xff01; 周五晚间&#xff0c;花旗、摩根大通、高盛、富国和贝莱德团体爆雷。 花旗集团上一年第四季度每股收益低于预期&#xff0c;尽管营收好于预期。花旗集团Q4每股收益1.16美元&#xff0c;预期为1.17美元。财报发布之后一度暴降超3%&#xff1b;…

【机器学习之模型融合】Stacking堆叠法

目录 1、Stacking的基本思想&#x1f48d; 2、思考&#x1f48e; 3、在sklearn中实现Stacking&#x1f3af; 3.1、导入工具库和数据&#x1f455; 3.2、定义交叉验证评估函数&#x1f457; 3.3、个体学习器与元学习器的定义&#x1f357; 3.4、模型构建&#x1f36a; 4…

【Linux】创建新用户 sudo配置,添加信任

目录 一、创建新用户 二、sudo不被允许 三、添加信任用户 一、创建新用户 相关指令&#xff1a; adduser [用户名]&#xff1a;创建新用户 passwd [用户名]&#xff1a;修改用户密码 su [用户名]&#xff1a;切换到该用户 设置密码&#xff0c;重复输入两遍之后&#xff0…

大数据技术架构(组件)——Hive:环境准备1

1.0.1、环境准备1.0.1.0、maven安装1.0.1.0.1、下载软件包1.0.1.0.2、配置环境变量1.0.1.0.3、调整maven仓库打开$MAVEN_HOME/conf/settings.xml文件&#xff0c;调整maven仓库地址以及镜像地址<settings xmIns"http://maven.apache.org/SETTINGS/1.0.0"xmIns:xsi…

电脑磁盘占用率高怎么办?

Windows磁盘占用率高是一种普遍存在的问题&#xff0c;相信很多用户遇到过不止一次&#xff0c;它可能是在刚开机时、可能是在下载文件时、也可能是在开启关闭应用程序时……当磁盘占用高之后&#xff0c;您的计算机运行速度会变得像蜗牛一样缓慢&#xff0c;更糟糕的是有些电脑…

python 代码注释

文章目录写在前面使用方法plainEpytextGoogleNumpyreStructuredText相关程序包其他写在前面 如果说高效率的算法是一个项目的内核&#xff0c;那么完备的文档注释、API 接口则是项目的外壳&#xff0c;直接与客户交互。 pycharm 提供了 5 种 代码注释格式。 分别是 plain, epy…

Tslib配置文件ts.conf

默认&#xff1a; # Access plugins ################# Uncomment if you wish to use the linux input layer event interface module_raw input# For other driver modules, see the ts.conf man page# Filter plugins ################# Uncomment if first or last sample…

【运维心得】正确的校正mysql-slave及mysqldump

实践出真知&#xff0c;有些细节&#xff0c;记录下。本文不涉及主备知识&#xff0c;有需右转: https://blog.csdn.net/qq_26834611/article/details/121385550mysql 正确的dump 命令:0. 检查当前主库所在位置ip addr 查看虚拟ip所在位置 1. 备机数据库dump备份:mysqldump -ur…

【ChatGPT】注册OpenAI账号试用ChatGPT

主要参考&#xff1a; 手把手教你注册 AI 聊天机器人模型 ChatGPT&#xff1a;大体流程注册OpenAI账号试用ChatGPT指南&#xff1a; 相关网站 openai: https://beta.openai.com/signup直接登录charGPT&#xff1a;https://chat.openai.com/接入微信&#xff0c;1.2K&#xf…

OneKeyGhost工具进行备份还原windows操作系统

OneKeyGhost OneKey Ghost是一款设计专业、操作简便的绿色程序&#xff0c;能够在 Windows 下对任意分区进行一键备份、恢复&#xff0c;支持ISO文件、光盘、U盘里的GHO文件硬盘安装。 OneKeyGhost备份wind系统 系统需要包含两个磁盘&#xff0c;一个系统盘另外一个数据盘。 …

Linux-文件权限命令

用户及权限操作 d:表示文件夹&#xff0c;-&#xff1a;表示文件&#xff0c;后面每隔3个分别代表 u、g、o。 使用ls -l &#xff08;ll&#xff09;可查看文件&#xff08;目录&#xff09;的权限 使用 chmod 可修改文件权限&#xff0c;有两种使用格式&#xff1a;字母法…

剑指offer五道题,C++实现,看看自己能不能解出来。

第一道&#xff08;剑指offer46 把数字翻译成字符串&#xff09; 给定一个数字&#xff0c;我们按照如下规则把它翻译为字符串&#xff1a;0 翻译成 “a” &#xff0c;1 翻译成 “b”&#xff0c;……&#xff0c;11 翻译成 “l”&#xff0c;……&#xff0c;25 翻译成 “z”…