欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

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

时间:2023-08-10
排序算法

排序算法介绍

测试数据准备排序父类Sort的创建比较类排序算法

1.选择排序2.冒泡排序3.插入排序4.希尔排序5.归并排序

上述五种排序算法速度比较 排序算法介绍

我们可以将其分为两类:比较类和非比较类排序算法。
排序涉及到的相关概念:

稳定 :如果有a和两个变量值相等,排序前a在b前面,排序后a还是在b前面。
不稳定:和稳定相反,有可能a会跑到b的后面。
时间复杂度:对于排序数据的总操作次数,反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需要存储空间的容量,它也是数据规模n的函数。

排序算法分类定义排序算法类型比较类排序通过比较决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),所以也叫非线性时间比较类排序选择排序         冒泡排序         插入排序     希尔排序             归并排序    堆排序     快速排序非比较类排序不通过比较元素间的相对次序,它是可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。计数排序 桶排序 基数排序测试数据准备

package sort;import java.util.Random;public class ArrayData { //数据:完全随机,大致有序,大致平稳 private int type; private int[] arr = new int[10000]; private Random random = new Random(); public ArrayData(int type){ this.type = type; } public int[] makeData() { if (type == 0) { for (int i = 0; i < arr.length; i++) { arr[i] = random.nextInt(10000); } } else if (type == 1) { for (int i = 0; i < arr.length; i++) { arr[i] = (i + 1) * 100 + random.nextInt(300); } } else { for (int i = 0; i < arr.length; i++) { arr[i] = 5000 + i % 2 == 0 ? random.nextInt(500) : -random.nextInt(500); } } return arr; }}

排序父类Sort的创建

package sort;public abstract class Sort { public int[] arr; public Sort(){}; public Sort(int[] arr){ this.arr = new int[arr.length]; for(int i=0;i 比较类排序算法 1.选择排序

选择排序是一种简单直观的排序算法,它的工作原理是首先在没有排序的序列中找到最大(小)元素,存放到排序序列的起始位置;然后再从剩余未排序的元素中继续寻找最大(小)元素,放到序列的已经排序序列的末尾,直至所有元素均排序完成。
其时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:不稳定
我们是使用双层循环遍历,外层为i,内层为j,判断从i+1到最后一个元素下标,只要这个范围内有数字比下表i的值小(从小到大排序),则进行交换;

package sort;import java.util.Arrays;public class SelectionSort extends Sort{ //数据分布,完全随机,大致有序,大致平稳 //算法的执行时间除了与算法的策略有关之外,还与数据分布有关系; public SelectionSort(int[] arr){ super(arr); } @Override public void sort() { for(int i = 0;i arr[j]){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } System.out.println(Arrays.toString(arr)); }}

2.冒泡排序

冒泡排序是一种间的排序算法,他重复的走访要排序的数列,一次比较两个元素,如果它们的顺序错误就交换一下,走访数列的工作是重复的,直到没有需要交换的,也就是该数列已经排序完毕。
其时间复杂度为:O(n^2)
空间复杂度为:O(1)
稳定性:稳定

动态图:

package sort;import java.util.Arrays;public class BubbleSort extends Sort{ public BubbleSort(int[] arr){ super(arr); } @Override public void sort() { for(int i=0;i arr[j+1]){ int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } System.out.println(Arrays.toString(arr)); }}

3.插入排序

它的工作原理是通过构建有序序列,对于未排序序列,再已经有序的序列中从后往前扫描,找到相应的插入位置并插入。
它的时间复杂度为;O(n^2)
空间复杂度为:O(1)
稳定性:稳定

动态图演示:

代码实现:

package sort;import java.util.Arrays;public class InsertionSort extends Sort{ public InsertionSort(int[] arr){ super(arr); } @Override public void sort() { for(int i=1;i0&&arr[j-1]>e;j--){ arr[j] = arr[j-1]; } arr[j] = e; } System.out.println(Arrays.toString(arr)); }}

4.希尔排序

也叫缩小增量排序,它是第一个突破O(n^2)的排序算法;
它是插入排序的升级版,相比插入排序它的步长为1,所以我们定义一个变量向前减减即可,但是希尔排序的步长不定,核心还是插入排序;
其时间复杂度为:O(n^1.3)
空间复杂度为:O(1)
稳定性:不稳定

动态图演示:

代码实现:

package sort;import java.util.Arrays;public class ShellSort extends Sort{ public ShellSort(int[] arr){ super(arr); } @Override public void sort() { int len = arr.length; for(int gap = len / 2;gap> 0;gap=gap/2){ for(int i = gap;i= 0 && arr[j-gap] > e) { arr[j] = arr[j - gap]; j = j-gap; } arr[j] = e; } } System.out.println(Arrays.toString(arr)); }}

5.归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法采用分治法的一个非常典型的应用,将已有序的子序列合并,得到完全有序的序列;也就是先让每个子序列有序,再让子序列段间有序。若将两个有序表合并为一个有序表,成为二路归并。
其时间复杂度为:O(nlogn)
空间复杂度为:O(n)
稳定性:稳定

动态图:

代码实现:

package sort;import java.util.Arrays;public class MergeSort extends Sort { public MergeSort(int[] arr){ super(arr); } @Override public void sort() { mergeSort(0,arr.length-1); System.out.println(Arrays.toString(arr)); } private void mergeSort(int L, int R) { //当做指针大于等于右指针则递归结束; if(L >= R){ return; } int mid = (L+R) / 2; mergeSort(L,mid);//先左后右; mergeSort(mid+1,R) //如是前面的最后一个比后面的第一个元素大才向上递归。 if(arr[mid] > arr[mid+1]){ merge(L,mid,R); } }//向上合并数列 private void merge(int L,int mid, int R) { //先将原数组复制一份; int[] aux = new int[R-L+1]; for(int k=L;k<=R;k++){ aux[k-L] = arr[k]; } int i = L; int j = mid+1; //判断如是前面部分已经排完,则后面部分直接赋值即可,反之一样; //若是都没完,则判断两部分那个元素值小先赋值。 for(int k=L;k<=R;k++){ if(i>mid){ arr[k] = aux[j-L]; j++; }else if(j > R){ arr[k] = aux[i-L]; i++; }else if(aux[i-L] < aux[j-L]){ arr[k] = aux[i-L]; i++; }else{ arr[k] = aux[j-L]; j++; } } }}

上述五种排序算法速度比较

package sort;public class TestSort { public static void main(String[] args) { //0 完全随机 1 大致有序 2 大致平稳 数据量为10000个 ArrayData data = new ArrayData(0); //ArrayData data = new ArrayData(1); //ArrayData data = new ArrayData(2); int[] arr = data.makeData(); test01(arr); test02(arr); test03(arr); test04(arr); test05(arr); } private static void test01(int[] arr){ BubbleSort bubbleSort = new BubbleSort(arr); Long start = System.currentTimeMillis(); bubbleSort.sort(); Long end = System.currentTimeMillis(); System.out.println("冒泡排序所用时间:"+ (end - start)); } private static void test02(int[] arr){ SelectionSort selectionSort = new SelectionSort(arr); Long start = System.currentTimeMillis(); selectionSort.sort(); Long end = System.currentTimeMillis(); System.out.println("选择排序所用时间:"+ (end - start)); } private static void test03(int[] arr){ InsertionSort insertionSort = new InsertionSort(arr); Long start = System.currentTimeMillis(); insertionSort.sort(); Long end = System.currentTimeMillis(); System.out.println("插入排序所用时间:"+ (end - start)); } private static void test04(int[] arr){ ShellSort shellSort = new ShellSort(arr); Long start = System.currentTimeMillis(); shellSort.sort(); Long end = System.currentTimeMillis(); System.out.println("哈希排序所用时间:"+(end - start)); } private static void test05(int[] arr){ MergeSort mergeSort = new MergeSort(arr); Long start = System.currentTimeMillis(); mergeSort.sort(); Long end = System.currentTimeMillis(); System.out.println("归并排序所用时间:"+ (end - start)); }}



Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。