ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

常见排序算法

2021-04-12 19:57:10  阅读:147  来源: 互联网

标签:tmp 元素 int 常见 gap ++ 算法 排序


这些基础的算法真是容易忘,一段时间不写细节就不会处理了。在此记录一下。

1、初级的桶排序

如需要对10以内的数进行排序,可以先初始化一个长度为10的数组。然后遍历,遍历到哪个数就将数组对应的下标加1,如遍历到3,则a[3]++。整个遍历结束后,再通过输出数组即可得到有序数据。需要注意的是,a[i]是多少则需要打印多少次。
这种算法相当于是用下标记录数据,用值记录次数。

该算法的优点是快速,其时间复杂度是O(n)。但是该算法的缺点是占用过多的空间,如果需要对10000个数排序,那么需要申请长度10000数组来存储,相当于用空间换时间。

参考代码如下:

/**
 * 简单的桶排序(实际的桶排序要比这个复杂)
 * @param a 待排序的数组
 */
public static void bucketSort(int[] a) {
    // 先定义桶
    int[] tong = new int[10];      // 假设a数组存放的是10以内的数据,故需要定义10个桶
    for (int i = 0; i < tong.length; i++) {
        tong[i] = 0;   // 初始化桶中的每一位数 (假设待排序的数中不存在-1)
    }

    // 遍历待排数据,将数据放入到相应的桶中
    for (int i = 0; i < a.length; i++) {
        tong[a[i]]++;
    }

    // 输出桶中的数据,即已经排序好的数据
    for (int i = 0; i < tong.length; i++) {
        // 只打印存放了数据的桶
        if (tong[i] != 0) {
            for (int j = 0; j < tong[i]; j++) {
                // 在某个桶的位置上重复了几次,那么就打印多少次
                System.out.print(i + ",");
            }
        }
    }
}

2、冒泡排序

冒泡排序的思想是通过依次比较相邻的两个数的,如果顺序不对,则进行调换。在每一真趟的的冒泡的过程中,只能将一个数归位。在对n个数排序中,只需将n-1归位即可。故排序n个的数只需要n-1趟。该算法的优点是理解及实现难度不在,但是时间复杂度为O(n2)。

参考代码如下:

/**
 * 冒泡排序
 * @param a
 */
public static void bubbleSort(int[] a) {
    // 将一个元素依次与其他元素比较,冒泡到最后为一趟
    // n个元素只需要将n - 1个数归位,即需要n - 1趟

    int count = a.length - 1;   // 需要比较的次数
    for (int i = 1; i <= count; i++) {

        boolean hasSwap = false;    // 当前趟有没有发生交换,这样可以优化一下冒泡排序算法。

        // 第i趟时,只需比较count-i+1次,因为乘余的数已经排好序了。
        for (int j = 0; j <= count - i; j++) {
            if (a[j] > a[j + 1]) {
                int tmp = a[j + 1];
                a[j + 1] = a[j];
                a[j] = tmp;
                hasSwap = true;
            }
        }

        // 如果没有发生过交换,则说明已经排好序了
        if (!hasSwap) {
            System.out.println("第" + i + "趟排序已经排好的,结束排序");
            break;
        }
    }

    /**
     * 冒泡时间复杂度推导:
     * 第一趟要迭代 n - 1次
     * 第二趟      n - 2次
     *
     *
     * 第n-1趟,   1次
     * 累积求和即是 (n - 1) + (n - 2) + (n - 3) + ..... + 1;
     * n (n - 1) / 2
     * 故时间复杂度是: O(n2)
     */
}

3、快速排序

快速排序是一种基于二分的思想。由于其比较是跳跃式的,故比冒泡排序要快很多,但是最差的情况下等同于冒泡排序。

参考代码如下:

/**
 * 快速排序
 *
 * @param a
 * @param left 排序的范围 左起点
 * @param right 右起点
 */
public static void quickSort(int[] a, int left, int right) {
    // 递归停止条件
    if (left > right) {
        return;
    }

    int i = left;
    int j = right;
    int temp = a[left];    // 选定第一个元素为基准元素

    while (i < j) {
        // 因为基准元素是最左边的,故首先要从最右边开始找到一个比基准元素小的元素,j为其索引。顺序很重要。同时这里是a[j] >= temp,不能掉了等号。
        while (a[j] >= temp && i < j) {
            j--;
        }

        // 从左边开始找到一个比基准元素大的元素,i为其索引
        while (a[i] <= temp && i < j) {
            i++;
        }

        // 当i与j没有相遇时才交换,相遇时则表明此次基准数已经归位
        if (i < j) {
            // 交换i和j的位置
            int tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }
    }

    // i 与 j 相遇后将基准元素与i处的互换
    a[left] = a[i];
    a[i] = temp;

    // 将基准元素左边的排序
    quickSort(a, left, i - 1);
    // 同上,将基准元素右边的排序
    quickSort(a, j + 1, right);
}

4、插入排序

for (int i = 0; i < nums.length; i++) {
	// 当前值与前一个相比, 始终记住这个。 
    int j = i - 1;
    int tmp = nums[i];

    while (j >= 0 && tmp < nums[j]) {
    	// j往后挪动,因为j + 1 = i,当前值已经保存在tmp了,故无需担心nums[j + 1]的值被覆盖。 
        nums[j + 1] = nums[j];
        j--;
    }
	
	// 找到相应的位置挺好入
    nums[j + 1] = tmp;
}

5、Shell排序

fun shellSort(a: IntArray) {

        var size = a.size
        var gap = size / 2     // 初始gap为数组长度的一半
        while (gap > 0) {

            // 如下代码的思想为插入排序思想
            for (i in gap until size) {
                var tmp = a[i]
                var j = i - gap // 如果此时j小于0,则会跳过while循环。a[j+gap]即为a[i]
                while (j >= 0 && a[j] > tmp) {
                    a[j + gap] = a[j]
                    j -= gap
                }
                a[j + gap] = tmp
            }

            gap /= 2    // gap每次减半
        }
    }

标签:tmp,元素,int,常见,gap,++,算法,排序
来源: https://blog.csdn.net/honeysx/article/details/114649253

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有