资讯专栏INFORMATION COLUMN

常见排序算法及其实现(Binary,Insert、Select、Quick、Bubble.etc.S

187J3X1 / 1364人阅读

摘要:常见排序算法及其实现说明如果有幸能看到本文中的代码是参考编程思想某培训机构。若两个记录和的关键字相等,但排序后的先后次序保持不变,则称为这种排序算法是稳定的。

常见排序算法及其实现 说明

如果有幸能看到

1、本文中的代码是参考《Java编程思想》、某培训机构。

2、文中的代码放Github了,有兴趣的可以看看,点个star鼓励下我。

3、代码在Sublime中敲的,坑爹的GBK,注释了很多中文,一转码不能用了!!!

4、重点在思想,而不是实现 。再次推荐《Java编程思想》

5、如有拼写错误,还请谅解。本文只为自己复习使用,最后放了两个收藏非常有水准的文章链接。

数据结构之排序

排序:假设含有n个记录的序列{R1,R2,R3..,Rn},其中的关键字序列为{K1,K2,K3...,Kn}。将这些记录重新排序为{Ri1,Ri2,Ri3,Rin} ,使得相应的关键字满足Ki1<=Ki2<=..<=Kim,这样的一种操作被称为排序。

通常来说,排序的目的是快速查找

衡量排序算法的优势:

1、时间复杂度:分析关键字的比较次数和记录的移动次数。

2、空间复杂度:分析排序算法中需要多少辅助内存。

3、若两个记录A和B的关键字相等,但排序后A、B、的先后次序保持不变,则称为这种排序算法是稳定的。

排序算法分类:内部排序和外部排序

内部排序:整个排序过程不需要借助于外部存储器(如此攀等),整个排序在内存中完成。

外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器,外部排序最常见的是多路归并排序,可以认为外部排序由多次内部所组成。

常用的内部排序

选择排序

直接选择排序

堆排序

交换排序

冒泡排序

快速排序

插入排序

直接插入、折半插入

归并排序

桶式排序

基数排序

选择排序

基本原理:
将待排序的元素分为已排序和未排序,依次将为排序的元素中最小的元素放入已排序的组中,

直接排序简单直观,但性能略差:堆排序是一种较为搞笑的选择排序。但实现起来略为复杂。

代码实现:

import java.util.Arrays.*;
//选择排序,
public class SelectSort{
    public static void selectSort(int[] data) {

        int arrayLength = data.length;
        for (int i = 0; i < arrayLength - 1 ; i++ ) {
            for (int j= i +1; j < arrayLength; j++ ) {
                if (data[i] > data[j]) {
                    swap(data,i,j);
                }
            }
        }
        System.out.println("排序后 " + java.util.Arrays.toString(data));


    }

  //第一种通过临时变量来完成交换
  //注意这里可以用另外一中一种方式
    static void swap(int[] data,int i,int j) {
            int tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }


    public static void main(String[] args) {
        int[] data = {3,4,2,6,8,1,9};
        selectSort(data);
    }
}

改进版的选择排序:

//选择排序算法
//选择排序算法
//1、主要思想就是每次假设一个最小的值
public class SelectSort1 {
    public static void selectSort1(int[] data) {
        int arraylength = data.length;
        for (int i = 0; i < arraylength - 1; i++ ) {
            int minIndex = i;      //每次假设一个最小值下标
            for (int j = i + 1; j < arraylength ; j++ ) {
                if (data[minIndex] > data[j]) {
                minIndex = j;
                }
            }
            //判断需要交换的下标是否为自己
            if (minIndex != i) {
                 data[minIndex] = data[minIndex] + data[i];
                 date[i] = date[minIndex] - data[i];
                 data[minIndex] = data[minIndex] - data[i];
            }

        }
        //输出结果
        for (int d :data ) {
            System.out.println("排序之后:" + d);
        }
    }

    public static void main(String[] args) {
        int[] data = {3,4,2,6,8,1,9};
        selectSort1(data);
    }
}

直接选择排序效率分析

算法的时间效率:无论初始化状态如何,在第i趟排序中选择最小的元素,需要n-1次比较

算法的空间效率:空间效率较高,只需要一个附加程序单元用于交换,其空间效率为O(1)

算法的稳定性:不稳定

堆排序

资料和代码来自这家,有一种感觉,年代越远,越重视基础。现在的培训呢?

堆排序就是把最大堆堆顶的最大数取出,将剩余的堆继续调整为最大堆,再次将堆顶的最大数取出,这个过程持续到剩余数只有一个时结束

最大堆调整(Max-Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点

创建最大堆(Build-Max-Heap):将堆所有数据重新排序,使其成为最大堆

堆排序(Heap-Sort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

这个有点难啊,下一个。回来再来看。

冒泡排序

相邻两元素进行比较,如有需要则进行交换,每完成一次循环就将最大元素排在前面(从小到大排序)下一次循环是将其他的数进行类似的比较。

代码实现:

//冒泡排序
public class BubbleSort {
    static void sort(int[] data) {
        int len = data.length;
        for (int i = 0; i < len - 1; i++ ) {
            for (int j = 0 ; j < len - 1 - i; j++ ) {
                if (data[j] > data[j + 1]) {
                    swap(data,j,j+1);
                }
            }
        }

    }
    static void swap(int[] data,int i,int j) {
        int tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
    }

    public static void main(String[] args) {
        int[] data = {4,2,6,8,2,1,0};
        sort(data);
        for(int d : data) {
            System.out.print("->" + d);
        }
    }
}

冒泡排序效率分析:

算法的时间效率:从冒泡排序的算法可以看出,若待排序的元素为正序,则只需进行一趟排序,比较次数为n-1次,移动元素次数为0;若待排序的元素为逆序,则需要进行n-1趟排序.

算法的空间效率:空间效率很高,只需要一个附加程序单元用于交换,其空间效率为O(1)

算法的稳定性:稳定

快速排序

快速排序(Quick Sorting)基本思想是:任取待排序序列中的某个元素为界点,通过一次划分,将待排序元素分为左右两个子序列,左子序列元素的排列序列均小于界点元素的排序码,右子序列的排序码则大于或等于界点的排序码,然后分别对两个字序列继续进行划分,直至每一个序列只有一个元素为止。

一定要认真啊,认真啊,认真啊!!!
代码实现:

//快速排序
public class QuickSort {
    private static void swap(int[] data,int i,int j) {
        int tmp = data[i];
        data[i] = data[j];
        data[j] = tmp;
    }

    private static void subSort(int[] data,int start,int end) {
        if (start < end) {
         int base = data[end];

         int i = start;
         int j = end + 1;

         while(true) {
             while(i < end && data[++i] <= base) ;
             while(j > start && data[--j] >= base);
             if (i > j) {
                 swap(data,i,j);
             }else {
                 break;
            }
        }

            swap(data, start, j);
            subSort(data, start, j - 1);
            subSort(data, j + 1, end);
        }

    }
    public static void quickSort(int[] data) {
        subSort(data,0,data.length - 1);
    }

    public static void main(String[] args) {
        int[] data = {9,5,6,88};
        quickSort(data);
        System.out.print(java.util.Arrays.toString(data));
    }
}

插入排序

基本思想:每次将一个待排序的元素,按其关键字的大小插入到前面已经排好序的子序的合适位置,直到全部记录插入完成。

* 插入算法.
* 1,从后向前找到合适的位置插入
* 基本思想:每步将一个待排序的记录,按其顺序码大小插入到前面已经排好的子序列的合适位置
* 直到全部插入为止
*/
public class InsertSort {
   public static void main(String[] args) {
       //待排序的数列
       int[] nums = {43, 23, 64, 24, 34, 78, 32};
       //控制比较的轮数
       for (int i = 1; i < nums.length; i++) {
           //记录操作数
           int temp = nums[i];
           int j = 0;
           for (j = i - 1; j >= 0; j--) {
               //后一个和前一个比较,如果前面的大,则把前面的赋值到后面。
               if (nums[j] > temp) {
                   nums[j+1] = nums[j];
               } else {
                   break;
               }
           }
           if (nums[j + 1] != temp) {
               nums[j + 1] = temp;
           }
       }
       //输出结果
       for(int n : nums) {
           System.out.println(n);
       }
   }
}

直接插入排序:

直接插入排序 的基本思想:把n个待排序的元素堪称为一个有序表和无序表,开始时有序表中只包含一个元素,无序表中有n-1个元素,排序过程中每次从无序表中取出第一个元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。

代码实现:

//直接插入排序
public class InsertSort {
    public static void insertSort(int[] data) {
        int arrayLength = data.length;
        for (int i = 1; i < arrayLength; i++) {
            int tmp = data[i];

            if (data[i] < data[i -1]) {
                int j = i - 1;
                for (;j >=0 && data[j] > tmp; j-- ) {
                    data[j + 1] = data[j];
                }
                data[j + 1] = tmp;
            }

        }
    }
    public static void main(String[] args) {
        int[] data = {5,2,6,9};
        insertSort(data);
        for (int d :data ) {
            System.out.print(" " + d);

        }
    }
}

折半插入排序

折半插入排序是对直接插入排序的简单改进。

此处介绍的折半插入,其实就是通过不断地折半来快速确定第i个元素的插入位置,这实际上是一种查找算法:折半查找。Java的Arrays类里的binarySearch()方法,就是折半查找的实现,用于从指定数组中查找指定元素,前提是该数组已经处于有序状态。

与直接插入排序的效果相同,只是更快了一些,因为折半插入排序可以更快地确定第i个元素的插入位置

代码实现:

//折半插入排序
public class BinaryInsertSort{
    public static void binaryInsertSort(int[] data) {
        int len = data.length;
        for (int i = 1; i < len; i++) {
            int tmp = data[i];
            int low = 0;
            int high = i - 1;
            while(low <= high) {
                int mid = (low + high) / 2;
                if (tmp > data[mid]) {
                    low = mid + 1;
                }
                else {
                    high = mid -1;
                }

            }for (int j = i;j > low ; j-- ) {
                data[j] = data[j - 1 ];
            }
            data[low] = tmp;
        }
    }

    public static void main(String[] args) {
        int[] data = {5,2,7,3,9};
        binaryInsertSort(data);
        for (int d : data) {
            System.out.print(" " + d);
        }
    }
}

/**
 * Created by guo on 2018/2/2.
 * 二分查找法(折半查找):前提是在已经排好序的数组中,通过将待查找的元素
 * 与中间索引值对应的元素进行比较,若大于中间索引值对应的元素,去右半边查找,
 * 否则,去左边查找。依次类推。直到找到位置;找不到返回一个负数
 */
public class BinarySearchSort {
    public static void main(String[] args) {
        //必须保证数列是有序的
        int[] nums = {12, 32, 55, 67, 87, 98};
        int i = binarySearch(nums, 87);
        System.out.println("查找数的下标为:" + i);   //输出下标为4
    }

    /**
     * 二分查找算法
     *
     * @param nums
     * @param key
     * @return
     */
    public static int binarySearch(int[] nums, int key) {
        int start = 0;             //开始下标
        int end = nums.length - 1; //结束下标
        while (start <= end) {     //开始位置不能穿过结束位置 --start-->|<--end--
            int middle = (start + end) / 2;
            // 如果查找的key比中间的大,则去掉左边的值
            if (key > nums[middle]) {
                start = middle + 1;
             //如果查找的key比中间的小,则去掉右边的。
            } else if (key < nums[middle]) {
                end = middle - 1;             //结束位置需要向前移一位。
            } else {
                return middle;
            }
        }
        //找不到则返回-1
        return -1;
    }
}

先到这里吧,后续还得多敲几遍,需要学习的太多了,gogogo。

给大家放两个链接,GitHub、GitHub。里面收集的文章非常有水准,点进去不会失望的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68683.html

相关文章

  • 排序算法

    摘要:排序代码实现和一概念排序算法的稳定性稳定性稳定排序算法会让原本有相等键值的纪录维持相对次序。交换的结果导致结点的值变化了,重复,,的操作,直到没有孩子时跳出代码实现构建初始堆堆排序算法思想大顶堆举例将待排序的序列构造成一个大顶堆。 排序 代码实现:Java 和 Python 一、概念 1.1 排序算法的稳定性 稳定性:稳定排序算法会让原本有相等键值的纪录维持相对次序。也就是如果一个排序...

    kevin 评论0 收藏0
  • 排序算法

    摘要:排序代码实现和一概念排序算法的稳定性稳定性稳定排序算法会让原本有相等键值的纪录维持相对次序。交换的结果导致结点的值变化了,重复,,的操作,直到没有孩子时跳出代码实现构建初始堆堆排序算法思想大顶堆举例将待排序的序列构造成一个大顶堆。 排序 代码实现:Java 和 Python 一、概念 1.1 排序算法的稳定性 稳定性:稳定排序算法会让原本有相等键值的纪录维持相对次序。也就是如果一个排序...

    binaryTree 评论0 收藏0
  • Python_数据结构与算法

    摘要:什么是数据结构数据的组织结构方式一组数据如何存储,基本数据类型,,的封装算法与数据结构的区别数据结构只是静态的描述了数据元素之间的关系。高效的程序需要在数据结构的基础上设计和选择算法。 数据结构和算法基础 什么是数据结构和算法:兵法,计算的方法。算法是独立存在的一种解决问题的方法和思想。 算法的特征: 输入:算法具有0个或多个输入 输出:算法至少有1个或多个输出 有穷性:算法在有限的...

    Kylin_Mountain 评论0 收藏0

发表评论

0条评论

187J3X1

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<