IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 排序算法。 -> 正文阅读

[数据结构与算法]排序算法。

菜鸟教程

Acwing

在这里插入图片描述

在这里插入图片描述

冒泡排序

在这里插入图片描述

void bubble_sort(T arr[], int len){
    for(int i = 0; i < len - 1; i ++){
        for(int j = 0; j < len - 1 - i; j ++){
            if(arr[j] > arr[j + 1]){
                swap(arr[j], arr[j + 1]);
            }
        }
    }
}

选择排序

在这里插入图片描述

void selection_sort(vector<T>& arr){
    for(int i = 0; i < arr.size() -1; i ++){
        int min = i;
        for(int j = i + 1; j < arr.size(); i ++){
            if(arr[j] < min) min = j;
        }
        swap(arr[j], arr[min]);
    }
}

插入排序

有直接插入排序和折半插入排序两种

在这里插入图片描述

void insertion_sort(int arr[], int len){
    for(int i = 1; i < len; i++){
		int key = arr[i];
        int j = i - 1;
        while((j >= 0) &&  (key < arr[j])){
            arr[j + 1] = arr[j];
            j --;
        }
        arr[j + 1] = key;
    }
}

希尔排序

思想:设计一个增量序列,最后一次一定是1

每趟排序,把待排序记录分成若干子序列,分别插入排序

在这里插入图片描述

void shell_sort(T array[], int length){
    int h = 1;
    while(h < length / 3){
        h = 3 * h + 1;
    }
    while(h >= 1){
        for(int i = h; i < length; i++){
            for(int j = i; j >= h && array[j] < array[j - h]; j -= h){
                swap(array[j], array[j - h]);
            }
        }
        h = h / 3;
    }
}

归并排序

在这里插入图片描述

void merge_sort(int q[], int l, int r){
    if(l >= r) return;
    int mid  = l + r >> 1;
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);
    
    int k = 0, i = 1, j = mid + 1;
    while(i <= mid && j <= r)
        if(q[i] <= q[j]) tmp[k ++] = q[i ++];
    	else tmp[k ++] = q[j ++];
    
    while(i <= mid) tmp[k ++] = q[i ++];
    while(j <= r) tmp[k ++] = q[j ++];
    
    for(i = l, j = 0,i <= r; i++, j ++) q[i] = tmp[j];
}

快速排序

在这里插入图片描述

void quick_sort(int q[], int l, int r){
    if(l >= r) return;
    int i = l -1, j = r + 1, x = q[l + r >>1];
    while(i < j){
        do i ++; while(q[i] < x);
        do j --; while(q[j] > x);
        if(i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j), quick_sort(q, j+ 1, r);
}

堆排序

思想:大根堆

在这里插入图片描述

//将以k为根结点的树调整为大根堆 
void HeadAdjust(int a[], int k, int len){//注:除k结点外其他已经有序 
    a[0] = a[k];//a[0]暂存子树根节点 
    for(int i = 2 * k; i <= len; i *= 2){//沿较大子结点筛选 
        if(i < len && a[i] < a[i + 1]) i ++;//i为较大子结点下标 (i<len表示k有右孩子) 
        if(a[0] >= a[i]) break;//筛选结束 
        else{
            a[k] = a[i];//递归处理子结点 
            k = i;
        }
    }
    a[k] = a[0];
}

//建大根堆 时间复杂度---O(n)  
void BuildHeap(int a[], int len){//从下往上建堆,从最后一个叶子结点的根节点开始 
    for(int i = len / 2; i > 0; i --){//处理所有非终端结点 
        HeadAdjust(a, i , len);
    }
}//建堆过程关键字的比较次数不超过4n(定理) 

//堆排序的完整逻辑
void HeapSort(int a[], int len){
    BuildHeap(a, len);//建堆 O(n) 
    for(int i = len; i > 1; i --){//从后往前处理 ,共n-1趟交换和调整 
        swap(a[i], a[1]);//将堆顶元素(最大元素)与堆底元素交换 
        HeadAdjust(a, 1, i - 1);//把剩余待排元素调整为堆 
    }
}//每趟时间复杂度不超过o(h) =  O(logn),共 n-1趟 

计数排序

思想:每个桶只存储一个单一的值

朴素版 根据最大值开辟存储空间且不稳定

在这里插入图片描述

void count_sort(int a[], int n){
    int minval  = a[0], maxval = a[0];
    for(int i = 0; i < n; i++){
        minval = min(minval, a[i]);
        maxval = max(maxval, a[i]);
    }
    
    int cnt[maxval + 1] = {0};
    
    for(int i = 0; i < n; i ++) cnt[a[i]] ++;
    
    for(int i = minval, k = 0; i <= maxval; i++){
        while(cnt[i] != 0){
            data[k ++] = i;
            cnt[i] --;
        }
    }
}

优化版 根据实际的数组长度开辟空间且不稳定

void count_sort(int a[], int n){
    int minval  = a[0], maxval = a[0];
    for(int i = 0; i < n; i++){
        minval = min(minval, a[i]);
        maxval = max(maxval, a[i]);
    }
    
    int d = maxval - minval + 1;
    int cnt[d] = {0};
    
    for(int i = 0; i < n; i ++) cnt[a[i] - minval] ++;
    
    for(int i = 0, k = 0; i <= maxval - minval; i++){
        while(cnt[i] != 0){
            data[k ++] = i + minval;
            cnt[i] --;
        }
    }
    
}

二次优化版 稳定排序

//二次优化 
void count_sort(int a[], int n){
    //遍历数组求得最大值和最小值
    int minval = a[0], maxval = a[0];
    for(int i = 0; i < n; i ++){ 
        minval = min(minval, a[i]);
        maxval = max(maxval, a[i]);
    }

    int d = maxval - minval + 1;// 计数数组的实际长度 
    int cnt[d] = {0};//根据最大值开辟新数组空间 

    //统计原数组中元素出现的次数
    for(int i = 0; i < n; i ++) cnt[a[i] - minval] ++;//将元素映射到a[0...d-1] 

    int sum = 0;
    for(int i = 0; i < d; i ++){//本质为前缀和数组,用于求位次 
        sum += cnt[i];//此处的cnt既为元素又为之前的元素和,即cnt[i] = cnt[i] + cnt[i - 1] 
        cnt[i] = sum;// 比如, cnt[5] = 3,表示分数95, 排名第 3 
    } 

    int sortArray[d];//sortArray[]存元素真实序列 
    for(int i = n - 1; i >= 0; i --){//将原数组元素从后往前遍历 
        sortArray[cnt[a[i] - minval] - 1] = a[i];
        cnt[a[i] - minval] --;
    }

    //将排序后的序列赋给原数组
    for(int i = 0, k = 0; i < d; i ++){
        data[k ++] = sortArray[i];
    }
}

桶排序

空间换时间

思想:把一个范围的数值分到一个桶

在这里插入图片描述

void bucket_sort(int a[], int n){
    int minval = a[0], maxval = a[0];
    for(int i = 0; i < n; i++){
        minval = min(minval, a[i]);
        maxval = max(maxval, a[i]);
    }
    
    int bnum = 10;//桶中的元素的个数
    int m = (maxval - minval) / bnum + 1;
    
    vector< vector<int>> bucket(m);
    
    for(int i = 0; i < n; i++) bucket[(a[i] - minval ) / bnum].push_back(a[i]);
    
    for(int i = 0; i < m; i++) sort(bucket.begin(), bucket.end());
    
    for(int i =0, k = 0; i < m; i++){
        for(int j = 0; j < bucket[i].size();j ++){
            data[k ++] = bucket[i][j];
        }
    }
}

基数排序

思想:把每一位的数字分到一个桶中

在这里插入图片描述

int maxbit(int data[], int n) //辅助函数,求数据的最大位数
{
    int maxData = data[0];              ///< 最大数
    /// 先求出最大数,再求其位数,这样有原先依次每个数判断其位数,稍微优化点。
    for (int i = 1; i < n; ++i)
    {
        if (maxData < data[i])
            maxData = data[i];
    }
    int d = 1;
    int p = 10;
    while (maxData >= p)
    {
        //p *= 10; // Maybe overflow
        maxData /= 10;
        ++d;
    }
    return d;
/*    int d = 1; //保存最大的位数
    int p = 10;
    for(int i = 0; i < n; ++i)
    {
        while(data[i] >= p)
        {
            p *= 10;
            ++d;
        }
    }
    return d;*/
}
void radixsort(int data[], int n) //基数排序
{
    int d = maxbit(data, n);
    int *tmp = new int[n];
    int *count = new int[10]; //计数器
    int i, j, k;
    int radix = 1;
    for(i = 1; i <= d; i++) //进行d次排序
    {
        for(j = 0; j < 10; j++)
            count[j] = 0; //每次分配前清空计数器
        for(j = 0; j < n; j++)
        {
            k = (data[j] / radix) % 10; //统计每个桶中的记录数
            count[k]++;
        }
        for(j = 1; j < 10; j++)
            count[j] = count[j - 1] + count[j]; //将tmp中的位置依次分配给每个桶
        for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中
        {
            k = (data[j] / radix) % 10;
            tmp[count[k] - 1] = data[j];
            count[k]--;
        }
        for(j = 0; j < n; j++) //将临时数组的内容复制到data中
            data[j] = tmp[j];
        radix = radix * 10;
    }
    delete []tmp;
    delete []count;
}

位图排序

思想:用对应的32bit位对应十进制的0-31个数

位移转换:

1.确定十进制数在数组中下标的位置 idx = b[i] / 32;

2.求十进制数对应0-31中的数 x = b[i] % 32;

3.利用位移操作 b[idx] += (1 << 1);

    @Test
    public void bitmap_sort()
    {
        int[] a = new int[]{1, 6, 22, 4, 7, 2, 8, 30, 25, 5, 67, 80, 54, 90, 142};
        int[] b = new int[1 + 142/ 32];

        for (int k : a) {
            int idx = k / 32;
            int x = k % 32;
            b[idx] += 1 << x;
        }

        for(int j = 0; j < b.length; j++){
            for(int i = 0; i < 32; i ++){
                if((b[j] >> i & 1) == 1) System.out.print(32 * j + i + " ");
            }
        }
    }

快速幂

m^k%p

思想:把k分成 2^0 + 2^1 + …

int qmi(int m, int k, int p){
    int res = 1 % p;
    while(k){
        if(k&1) res = res * m % p;
        m = m * m % p;
        k >> 1;
    }
    return res;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-26 09:06:11  更:2021-11-26 09:06:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 16:14:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码