当前位置: 首页 > news >正文

《算法导论》学习笔记——计数排序

计数排序

1.计数排序原理

  前面所涉及的插入排序、归并排序、堆排序、快速排序等算法都具有这样一个性质:在排序的最终结果中,各元素的次序依赖于它们之间的比较。因此我们将这类排序都称为比较排序。我们现在介绍新的三种排序:计数排序、基数排序和桶排序,这些算法是通过运算而不是比较来确定排序顺序的。这篇文章我们单讲计数排序。

  计数排序假设n个输入元素中的每一个都是在区间0到k内的整数,其中k为某一整数。当k = O(n)时,排序运行时间近似为O(n)。计数排序的思想如下:对于每一个输入元素x,确定小于元素x的个数。利用这一信息就可以直接把x放到它在输出数组中的位置了。譬如假若有7个元素小于x,那么x就在输出数组数组的第18个位置上,如果有相同大小的元素。对这一方案微调即可。

  因此,在计数排序算法中,假设输入是一个数组A[1...n],A.length = n。我们还需要两个数组:B[0...k]提供临时存储空间,C[1...n]存储排序的输入。伪代码如下(注:伪代码里面的数组B[]对应下面图示中的数组C[],伪代码里面的数组C[]对应下面图示中的数组B[]):

COUNT_SORT
    Let B[0...k] be a new array
    for i = 0 to k
        B[i] = 0
    for j = 1 to A.length
        B[A[j]] = B[A[j]] + 1
    // B[i] now contains the number of elements equal to i
    for i = i to k
        B[i] = B[i] + B[i - 1]
    //B[i] now contains the number of elements less than or equal to i
    for j = A.length down to 1
        C[B[A[j]]] = A[j]
        B[A[j]] = B[A[j]] - 1

  下图展示了计数排序的全过程。

221430414692923.png

  根据前面的叙述,可以得知计数排序的下界优于O(nlogn),因为它并不是一个比较排序的算法,实际上,可以看到基数排序的算法中完全没有两个元素之间的比较,计数排序是根据输入元素的实际值来确定其在数组中的位置。

  计数排序的一个重要性质就是它是稳定的据有相同值得元素在输出数组中的相对次序与他们在输入数组中的相对次序相同。也就是说,对两个大小相同的元素来说,在输入数组中先出现的元素,在输出数组中的次序也位于前面。一般来说,当进行排序的数组还附带卫星数据是这种稳定性就显得尤为重要,因此,计数排序经常会被用作基数排序算法的子过程,有关基数排序的算法我们在下一节论述。

2.代码实现(C,Java,Python)

  注意到数组下标是从0开始的,因此实现伪代码时一定要避免数组越界问题。

C

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int *array_a, *array_b, *array_c;

void count_sort(int length, int k) {
    int i;
    for(i = 0; i < k; i++)
        array_b[i] = 0;
    for(i = 0; i < length; i++)
        array_b[array_a[i]] += 1;
    for(i = 1; i < k; i++)
        array_b[i] += array_b[i - 1];
    for(i = length - 1; i >= 0; i--) {
        array_c[array_b[array_a[i]] - 1] = array_a[i];
        array_b[array_a[i]] -= 1;
    }
}


int main() {
    int length, k = 10, i;
    printf("Enter the lengrh of array: ");
    scanf("%d", &length);
    array_a = (int *)malloc(length * sizeof(int));
    array_b = (int *)malloc(k * sizeof(int));
    array_c = (int *)malloc(length * sizeof(int));
    srand((unsigned)time(NULL));
    for(i = 0; i < length; i++)
        array_a[i] = rand() % k;
    printf("The original array is:\n");
    for(i = 0; i < length; i++)
        printf("%d ", array_a[i]);
    printf("\n");
    count_sort(length, k);
    printf("The sorted array is:\n");
    for(i = 0; i < length; i++)
        printf("%d ", array_c[i]);
    free(array_a);
    free(array_b);
    free(array_c);
    return 0;
}

Java

import java.util.*;

public class CountSort{
    public static void display(Iterator<Integer> it){
        while (it.hasNext()){
            Integer element = it.next();
            System.out.print(element + " ");
        }
    }
    public static void main(String[] args){
        ArrayList<Integer> array = new ArrayList<Integer>();
        Scanner in = new Scanner(System.in);
        System.out.print("Enter the maximun number of the array: ");
        int max = in.nextInt();
        System.out.print("Enter the length of the array: ");
        int length = in.nextInt();
        Random rand = new Random();
        for (int i = 0; i < length; i++)
            array.add(rand.nextInt(max));
        in.close();
        display(array.iterator());
        System.out.println();
        Sort sort = new Sort(array);
        array = sort.countSort(max, length);
        display(array.iterator());
    }
}

class Sort{
    public Sort(ArrayList<Integer> array){
        this.array_a = array;
        this.array_b = new ArrayList<Integer>();
        this.array_c = new ArrayList<Integer>();
    }

    public ArrayList<Integer> countSort(int max, int length){
        for (int i = 0; i < max; i++)
            array_b.add(0);
        for (int i = 0; i < length; i++){
            array_b.set(array_a.get(i), array_b.get(array_a.get(i)) + 1);
            array_c.add(0);
        }
        for (int i = 1; i < max; i++)
            array_b.set(i, array_b.get(i) + array_b.get(i - 1));
        for (int i = length - 1; i >= 0; i--){
            array_c.set(array_b.get(array_a.get(i)) - 1, array_a.get(i));
            array_b.set(array_a.get(i), array_b.get(array_a.get(i)) - 1);
        }
        return array_c;
    }


    private ArrayList<Integer> array_a;
    private ArrayList<Integer> array_b;
    private ArrayList<Integer> array_c;
}

Python

countSort.py

import random

def countSort(maximum, length):
    array_a = [random.randint(0, maximum - 1) for i in range(0, length)]
    array_b = [0] * maximum
    array_c = [0] * length
    print "The original array is " + str(array_a)
    for i in range(0, length):
        array_b[array_a[i]] += 1
    for i in range(1, maximum):
        array_b[i] += array_b[i - 1]
    for i in range(length - 1, -1, -1):
        array_c[array_b[array_a[i]] - 1] = array_a[i]
        array_b[array_a[i]] -= 1
    return array_c

test.py

import countSort

sortedArray = countSort.countSort(5, 10)
print "The sorted array is " + str(sortedArray)

转载于:https://www.cnblogs.com/zhxbao/p/count_sort.html

相关文章:

  • H3C IPv6全网解决方案
  • 10. 星际争霸之php设计模式--原型模式
  • 发布一个练笔的 Android 阅读器,轻微仿91 Android 阅读器
  • python 第一个爬虫
  • C#文件操作
  • 通过日志恢复SQL Server的历史数据
  • DateTime Calendar
  • Sqlserver与Oracle 10g数据类型对照
  • win7、Ubuntu双系统Grub启动菜单修复
  • IT男吃什么最利于健康
  • 根据经纬度获取时区信息
  • 团购消费已成近期投诉热点 长假团购需防三大陷阱
  • 大数据架构和模式(五)——对大数据问题应用解决方案模式并选择实现它的产品...
  • 解决MSE, Windows Update/Defender无法更新(错误代码0x8024402F)
  • Android_CodeWiki_03
  • #Java异常处理
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 0x05 Python数据分析,Anaconda八斩刀
  • CentOS 7 修改主机名
  • HashMap ConcurrentHashMap
  • JAVA之继承和多态
  • js如何打印object对象
  • Making An Indicator With Pure CSS
  • ng6--错误信息小结(持续更新)
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • scala基础语法(二)
  • springMvc学习笔记(2)
  • swift基础之_对象 实例方法 对象方法。
  • vue总结
  • 记录一下第一次使用npm
  • 浏览器缓存机制分析
  • 消息队列系列二(IOT中消息队列的应用)
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • MPAndroidChart 教程:Y轴 YAxis
  • # 透过事物看本质的能力怎么培养?
  • #HarmonyOS:软件安装window和mac预览Hello World
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (12)Linux 常见的三种进程状态
  • (3)llvm ir转换过程
  • (C++)八皇后问题
  • (C++20) consteval立即函数
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (力扣题库)跳跃游戏II(c++)
  • (免费分享)基于springboot,vue疗养中心管理系统
  • .NET DataGridView数据绑定说明
  • .net实现客户区延伸至至非客户区
  • .NET与 java通用的3DES加密解密方法
  • @LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析
  • @RequestBody与@ResponseBody的使用
  • [] 与 [[]], -gt 与 > 的比较
  • [20140403]查询是否产生日志