十大经典排序算法

  • 1. 相关术语介绍
  • 2. 排序算法分类以及复杂度
  • 3.冒泡排序
  • 4 选择排序
    • 4.1 直接选择排序
    • 4.2 双向选择排序
  • 5. 插入排序
    • 5.1 直接插入排序
    • 5.2 折半插入排序
  • 6.希尔排序
  • 7.归并排序(递归+非递归)
  • 8.快速排序(递归+非递归)
    • 8.1 基础快速排序(递归+非递归)
    • 8.2 二路快速排序
    • 8.3 三路快速排序

1. 相关术语介绍

稳定排序:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
非稳定排序:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
内排序:所有排序操作都在内存中完成;
外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
时间复杂度:排序所耗费的时间;
空间复杂度:排序所耗费的内存;
比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序

2. 排序算法分类以及复杂度

排序算法分类
十大排序算法主要可以分为两大类:1.比较类排序 2.非比较类排序,下面是排序算法的分类

不同排序算法的复杂度以及稳定性

3.冒泡排序

下面对数据从小到大排序
思想:每次寻找一组数据中最大的元素,两两比较,找到后放到数据的最后一位。n个数据第一次两两比较n-1次。
第二次比较n-2次,比较的时候如果前一个元素比第二个元素大则相互交换。
总共两层循环:第一层代表需对比几轮;第二层代表需要两两对比多少次
以下面的图举例
15个数,第一轮两两对比49次找出15个数中最大的数50
第二轮两两对比48次找到次大数48
以此类推…
那总共需要多少轮呢?
15个数,需要14轮
每轮需要两两对比多少次呢?
很明显,每轮两两对比的次数不固定
第一轮两两对比14次找到最大数
第二轮需要对比13次,因为不用和最后一个数对比


C语言代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int BubbleSort(int arr[],int len)
{int temp = 0;for (int i = 0; i < len-1; i++){for (int j = 0; j < len-1-i; j++){if (arr[j] > arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}for (int i = 0; i < len; i++){printf("%d  ", arr[i]);}
}
int main()
{int arr[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 };int len = sizeof(arr) / sizeof(arr[0]);BubbleSort(arr,len);}

java代码

package sort;
import java.util.Arrays;
public class SelfSevenSort {// 冒泡排序// 在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序public static void BubbleSort(int[] arr){for (int i = 0; i < arr.length-1; i++) {for (int j = 0; j < arr.length-1-i; j++) {if(arr[j]>arr[j+1]){int tmp=arr[j];arr[j]=arr[j+1];arr[j+1]=tmp;}}}}public static void main(String[] args) {int[] arr={2,1,4,6,3,7,9,0};BubbleSort(arr);System.out.println(Arrays.toString(arr));}
}

4 选择排序

4.1 直接选择排序

选择排序:每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或最前),直到全部待排序的数据元素排完 。
每轮都找到一组数据中最小的数依次放在数组前面。
与冒泡排序的不同:冒泡排序在找数的时候,每次比较都需要进行数据交换,而选择排序是两两对比 记录数据 的索引,找到数据后只进行一次交换。
以对{ 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 }由小到大排列为例

C语言代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void selectionSort(int arr[], int len)
{int temp = 0;for (int i = 0; i < len-1; i++){int index = i;for (int j = i+1; j < len; j++){if (arr[j] < arr[index]){index = j;}}temp = arr[i];arr[i] = arr[index];arr[index] = temp;}for (int i = 0; i < len; i++){printf("%d  ", arr[i]);}
}
int main()
{int arr[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 };int len = sizeof(arr) / sizeof(arr[0]);selectionSort(arr, len);
}

java代码

package sort;
import java.util.Arrays;
public class SelfSevenSort {// 选择排序// 每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或最前),// 直到全部待排序的数据元素排完。public static void SelectionSort(int[] arr){// 最开始,无序区间[0...n]  有序区间[]// 当无序区间只剩下一个元素时,整个集合已经有序for (int i = 0; i < arr.length-1; i++) {int min=i;for (int j = i+1; j < arr.length; j++) {if (arr[j]<arr[min]){min=j;}}int tmp=arr[i];arr[i]=arr[min];arr[min]=tmp;}}public static void main(String[] args) {int [] arr1={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};SelectionSort(arr1);System.out.println(Arrays.toString(arr1));}
}

4.2 双向选择排序

双向选择排序:每一次从无序区间选出最小 + 最大的元素,存放在无序区间的最前和最后,直到全部待排序的数据元素排完 。
low:无序区间起始位置
high:无序区间终止位置
min:最小值索引
max:最大值索引

package sort;
import java.util.Arrays;
public class SelfSevenSort {// 双向选择排序
//    双向选择排序:每一次从无序区间选出最小 + 最大的元素,存放在无序区间的最前和最后,直到全部待排序的数据元素排完 。
//    low:无序区间起始位置
//    high:无序区间终止位置
//    min:最小值索引
//    max:最大值索引public static void SelectionSortOP(int[] arr){int low=0;int high=arr.length-1;// low = high,无序区间只剩下一个元素,整个数组已经有序while(low<=high){// 定义max min为无序区间的起始位置索引int max=low;int min=low;// 无序区间for (int i = low+1; i <= high; i++) {if(arr[i]<arr[min]){min=i;}if(arr[i]>arr[max]){max=i;}}int tmp=arr[low];arr[low]=arr[min];arr[min]=tmp;// 如果最大值对应的索引刚好是无序区间的起始位置,经过上面的调整,最大值被调整到了arr[min]位置if (max==low){max=min;}int tmp1=arr[high];arr[high]=arr[max];arr[max]=tmp1;high--;low++;}}public static void main(String[] args) {int [] arr1={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};SelectionSortOP(arr1);System.out.println(Arrays.toString(arr1));}
}

5. 插入排序

5.1 直接插入排序

整个区间被分为

  1. 有序区间
  2. 无序区间
    每次选择无序区间的第一个元素,在有序区间内选择合适的位置插入
    插入排序和选择排序最大的区别:当插入排序当前遍历的元素>前驱元素时,此时可以提前结束内层循环
    极端情况,当集合是一个完全有序的集合时,插入排序内层循环一次都不走,插入排序为O(n) 插入排序是许多高阶排序算法的优化基础

package sort;import java.util.Arrays;public class SelfSevenSort {// 插入排序// 整个区间被分为//1. 有序区间//2. 无序区间//每次选择无序区间的第一个元素,在有序区间内选择合适的位置插入public static void insrtSort(int[] arr){// 有序区间 已排序区间[0,i)for (int i = 1; i < arr.length; i++) {// 待排序区间[i...n]// 待排序区间的第一个元素arr[i]// 从待排序区间的第一个元素向前看,找到合适的插入位置for (int j = i; j >0 ; j--) {// arr[j - 1]已排序区间的最后一个元素// 相等我们也不交换,保证稳定性// 此时说明arr[j] > 已排序区间的最大值,arr[j]已经有序了~~直接下次循环if (arr[j]>=arr[j-1]){break;}else{int tmp=arr[j];arr[j]=arr[j-1];arr[j-1]=tmp;}}}}public static void main(String[] args) {int[] arr={2,1,4,6,3,7,9,0};BubbleSort(arr);System.out.println(Arrays.toString(arr));int [] arr1={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};insrtSort(arr1);System.out.println(Arrays.toString(arr1));}
}

5.2 折半插入排序

在有序区间用二分法选择数据应该插入的位置时,因为区间的有序性,可以利用折半查找的思想

package sort;
import java.util.Arrays;
public class SelfSevenSort {// 折半插入排序// 在有序区间用二分法选择数据应该插入的位置时,因为区间的有序性,可以利用折半查找的思想public static void inserttSortBS(int[] arr) {for (int i = 1; i < arr.length; i++) {int right = i;int left = 0;int val = arr[i];while (left < right) {int mid = left + ((right - left) >> 1);if (val < arr[mid]) {right = mid;} else {// val>=arr[mid]left = mid + 1;}}for (int j = i; j > left; j--) {arr[j] = arr[j - 1];}//  left就是val插入的位置arr[left] = val;}}public static void main(String[] args) {int[] arr = {2, 1, 4, 6, 3, 7, 9, 0};BubbleSort(arr);System.out.println(Arrays.toString(arr));int[] arr1 = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};inserttSortBS(arr1);System.out.println(Arrays.toString(arr1));}
}

6.希尔排序

希尔排序法又称缩小增量法
希尔排序法的基本思想是:先选定一个整数gap(gap一般为数组长度的一半或1/3),把待排序数组以gap为间隔分成个组,个组之间内部使用插入排序,排序之后,再将gap/=2或gap/=3,重复上述流程,直到gap=1,此时数组已经近乎有序,利用插入排序对近乎有序的数组进行调整。

例如
arr=[9,1,2,5,7,4,8,6,3,5] 数组长度为10 ,gap取5
将待排序数组以5为间隔分成5组[9,4] [1,8] [2,6] [5,3] [7,5]
5组内部分别利用插入排序进行调整
调整后[4,9] [1,8] [2,6] [3,5] [5,7]
此时arr=[4,1,2,3,5,9,8,6,5,7]
gap/2=2

package sort;import java.util.Arrays;public class SelfSevenSort {public static void swap(int[] arr,int i,int j){int tmp=arr[i];arr[i]=arr[j];arr[j]=tmp;}// 希尔排序// ap,gap一般为数组长度的一半或1/3,将待排序的数组先按照//gap分组,不同组之间内部使用插入排序,排序之后,再将//gap/=2或gap/=3,重复上述流程,直到gap=1,此时数组已经//近乎有序,利用插入排序对近乎有序的数组进行调整。public static void shellSort(int[] arr){int gap=arr.length>>1;while(gap>1){// 当gap>1时,对arr以gap为间隔进行分组,组内进行插入排序insertionSortBygap(arr,gap);gap = gap>>1;}// 此时gap==1,数组接近有序,对此时的arr进行插入排序insrtSort(arr);}// 对arr以gap为间隔进行分组,组内进行插入排序public static void insertionSortBygap(int[] arr,int gap){for (int i = gap; i < arr.length; i++) {for (int j = i; j - gap >= 0 ; j=j-gap) {if (arr[j]>arr[j-gap]){break;}if(arr[j]<arr[j-gap]){swap(arr,j,j-gap);}}}}public static void main(String[] args) {int[] arr2={9,1,5,8,3,7,4,6,2};shellSort(arr2);System.out.println(Arrays.toString(arr2));}
}

7.归并排序(递归+非递归)

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子
序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
将原数组不断拆分,一直拆到每个子数组只有一个元素时,第一个阶段结束,归而为1的过程


归并排序,递归写法

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.concurrent.ThreadLocalRandom;public class SelfSevenSort {//交换两个元素public static void swap(int[] arr,int i,int j){int tmp=arr[i];arr[i]=arr[j];arr[j]=tmp;}//  归并排序public static void mergeSort(int[] arr) {mergeSortInternal(arr,0,arr.length - 1);}// 在arr[l...r]进行归并排序,整个arr经过函数后就是一个已经有序的数组private static void mergeSortInternal(int[] arr, int l, int r) {if (l >= r) {// 当前数组只剩下一个元素,归过程就结束了return;}int mid = l + ((r - l) >> 1);// 将原数组拆分为左右两个小区间,分别递归进行归并排序mergeSortInternal(arr,l,mid);mergeSortInternal(arr,mid + 1,r);// merge  拆分结束,合并两个数组merge(arr,l,mid,r);}// 合并两个子数组arr[l..mid] 和 arr[mid + 1...r]// 为一个大的有序数组arr[l...r]private static void merge(int[] arr, int l, int mid, int r) {// 先创建一个新的临时数组auxint[] aux = new int[r - l + 1];// 将arr元素值拷贝到aux上for (int i = 0; i < aux.length; i++) {// 每次区间起始位置不同  因此 aux[i]对应arr[i+l]aux[i] = arr[i + l];}// 合并两个区间,i就是左侧小数组的开始索引,第一个区间int i = l;// j就是右侧小数组的开始索引int j = mid + 1;int count=0;// k表示当前正在合并的原数组的索引下标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];count=i ++;}else if (aux[i - l] <= aux[j - l]) {// 此时左侧区间的元素值较小,相等元素放在左区间,保证稳定性arr[k] = aux[i - l];i ++;}else {// 右侧区间的元素值较小arr[k] = aux[j - l];count++;j ++;}}}// 归并排序,小区间使用插入排序public static void insertionSort(int[] arr,int l,int r){for (int i = l; i < arr.length; i++) {for (int j = i; j-1>0; j--) {if (arr[j]>arr[j-1]){break;}if(arr[j]<arr[j-1]){swap(arr,j,j-1);}}}}public static void main(String[] args) {int[] arr2={9,1,5,8,3,7,4,6,2};mergeSort(arr2);System.out.println(Arrays.toString(arr2));}
}

非递归代码

/*** 归并排序的迭代写法* @param arr*/public static void mergeSortNonRecursion(int[] arr) {// 最外层循环表示每次合并的子数组的元素个数for (int sz = 1; sz <= arr.length; sz += sz) {// 内层循环的变量i表示每次合并的开始索引// i + sz 就是右区间的开始索引,i + sz < arr.length说明还存在右区间for (int i = 0; i + sz < arr.length ; i += sz + sz) {merge(arr,i,i + sz - 1,Math.min(i + sz + sz - 1,arr.length - 1));}}}

8.快速排序(递归+非递归)

8.1 基础快速排序(递归+非递归)

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

  1. 从待排序区间选择一个数,作为基准值(pivot);
  2. Partition: 遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的(可以包含相等的)放到基准值的右边;
  3. 采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序,或者小区间的长度 == 0,代表没有数据。

    思路:
    基准值选取最左侧的元素,对整个数组进行分区,橙色为小于基准值的区间,紫色为大于基准值的区间,e为正在遍历的元素。
    橙色区间 arr[l+1,j]
    紫色区间arr[j+1,i)

    将遍历的元素与基准值进行比较,有两种情况
    case1: arr[i] >= v,此时只需要 i++ 就行 紫色区域自动加1

    case2: arr[i]<v, 此时将紫色区域第一个大于等于v的元素与当前元素进行交换。swap(arr[j+1],arr[i])

    第一次将整个集合扫描完,整个区间被分为三部分

    此时交换arr[j]和arr[l],继续在两个区间上重复上述过程。
package sort;import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.concurrent.ThreadLocalRandom;public class SelfSevenSort {public static void swap(int[] arr,int i,int j){int tmp=arr[i];arr[i]=arr[j];arr[j]=tmp;}/*** 快速排序* @param arr*/public static void quickSort(int[] arr) {quickSortInternal(arr,0,arr.length - 1);}/*** 在arr[l..r]上进行快速排序* @param arr* @param l* @param r*/private static void quickSortInternal(int[] arr, int l, int r) {if (l>r) {return;}// 先获取分区点// 所谓的分区点就是经过分区函数后,某个元素落在了最终的位置// 分区点左侧全都是小于该元素的区间,分区点右侧全都是 >= 该元素的区间int p = partition(arr,l,r);// 重复在左区间和右区间上重复上述流程quickSortInternal(arr,l,p - 1);quickSortInternal(arr,p + 1,r);}/*** 在arr[l..r]上的分区函数,返回分区点的索引* @param arr* @param l* @param r* @return*/private static int partition(int[] arr, int l, int r) {//        // 随机在当前数组中选一个数
//        ThreadLocalRandom random=ThreadLocalRandom.current();
//        int randomIndex = random.nextInt(l,r);
//        swap(arr,l,randomIndex);int v = arr[l];// arr[l + 1..j] < v// arr[j + 1..i) >= v// i表示当前正在扫描的元素int j = l;for (int i = l + 1; i <= r; i++) {if (arr[i] < v) {swap(arr,j + 1,i);j ++;}}// 将基准值和最后一个 < v的元素交换,基准值就落在了最终位置swap(arr,l,j);return j;}}public static void main(String[] args) {int[] arr2={9,1,5,8,3,7,4,6,2};quickSort(arr2);System.out.println(Arrays.toString(arr2));}
}

快速排序非递归写法

 /*** 借助栈来实现非递归分治快排* @param arr*/public static void quickSortNonRecursion(int[] arr) {Deque<Integer> stack = new ArrayDeque<>();// 栈中保存当前集合的开始位置和终止位置int l = 0;int r = arr.length - 1;stack.push(r);stack.push(l);while (!stack.isEmpty()) {// 栈不为空时,说明子区间还没有处理完毕int left = stack.pop();int right = stack.pop();if (left >= right) {// 区间只有一个元素continue;}int p = partition(arr,left,right);// 依次将右区间的开始和结束位置入栈stack.push(right);stack.push(p + 1);// 再将左侧区间的开始和结束位置入栈stack.push(p - 1);stack.push(left);}

关于基准值的选取
1.选择边上(左或者右)(接近有序的数组上,快排退化成O(N^2)时间复杂度,左右区间严重不平衡)
2.随机选择
3.几数取中(例如三数取中)(array[left], array[mid], array[right] 大小是中间的为基准值)
2和3基准值的选择方法在接近有序的数组上,都能避免递归过程中,快速排序分区严重不平衡的问题
问题:当数组中重复元素较多时,就会导致分区后某个区间元素过多,会递归过程中,递归树严重不平衡,快排时间复杂度倒退到O(n^2)
为解决此问题,衍生出了两种解决方法:二路快排和三路快排

8.2 二路快速排序

二路快排在分区的时候将相等元素分到左右两个子区间

package sort;import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.concurrent.ThreadLocalRandom;public class SelfSevenSort {public static void swap(int[] arr,int i,int j){int tmp=arr[i];arr[i]=arr[j];arr[j]=tmp;}/*** 二路快排* @param*/public static void quickSort2(int[] arr){quickSortInternal2(arr,0,arr.length-1);}// 对 arr[l,r]进行快速排序private static void quickSortInternal2(int[] arr, int l, int r) {// 分区if (l>r) {return;}// arr[l,r]上求分区点,arr[l,p]都小于v,arr[p,r]都大于Vint p=partition2(arr,l,r);// 重复上述过程quickSortInternal2(arr,l,p-1);quickSortInternal2(arr,p+1,r);}// 二路快排的分区// 返回arr[l,r]上的分区点private static int partition2(int[] arr, int l, int r) {int v=arr[l];// arr[l + 1..i) <= v// [l + 1..l + 1) = 0int i=l+1;// arr(j..r] >= v// (r...r] = 0int j=r;while(true){// i从前向后扫描,碰到第一个 >= v的元素停止while(i<=j && arr[i]<v){i++;}// j从后向前扫描,碰到第一个 <= v的元素停止while(i<=j && arr[j]>v){j--;}if(i>=j){break;}swap(arr,i,j);i++;j--;return j;}// j落在最后一个 <= v的元素身上swap(arr,l,j);return j;}public static void main(String[] args) {int[] arr2={9,1,5,8,3,7,4,6,2};quickSort2(arr2);System.out.println(Arrays.toString(arr2));}
}

8.3 三路快速排序

将所有重复的元素都放在最终位置,只需要在小于V和大于V的子区间进行快排,所有相等的元素不再处理。
arr[l] 基准值
arr[l+1,It] 区间为小于V的元素集合
It为最后橙色小于V的区间中最后一个小于V 的元素
arr[It+1,i) 蓝色区间为等于基准值的区间
arr[i] 为当前遍历到的元素
gt 为紫色区间大于V的元素集合中第一个大于V 的元素
arr[gt,r] 紫色区间 大于V的集合

当扫描的元素ar[i] < v 时,交换arr[i]和第一个等于V的元素It+1

当扫描的元素ar[i] = v 时,不用处理,继续向前走

当扫描的元素ar[i] > v 时,交换当前遍历的元素arr[i]和紫色区间第一个> v的元素,但是此时不用继续向前走,因为交换过来的元素也是未处理的元素

整个集合处理完,交换j和l

package sort;import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.concurrent.ThreadLocalRandom;
public class SelfSevenSort {public static void swap(int[] arr,int i,int j){int tmp=arr[i];arr[i]=arr[j];arr[j]=tmp;}/*** 三路快排* @param*/public static void quickSort3(int[] arr) {quickSortInternal3(arr,0,arr.length - 1);}private static void quickSortInternal3(int[] arr, int l, int r) {if (l>r) {return;}
//        int randomIndex = random.nextInt(l,r);
//        swap(arr,l,randomIndex);int v = arr[l];// 这些变量的取值,一定是满足区间的定义,最开始的时候,所有区间都是空// arr[l + 1..lt] < v// lt是指向最后一个<v的元素int lt = l;// arr[lt + 1..i) == v// i - 1是最后一个 = v的元素int i = lt + 1;// arr[gt..r] > v// gt是第一个 > v的元素int gt = r + 1;// i从前向后扫描和gt重合时,所有元素就处理完毕while (i < gt) {if (arr[i] < v) {// arr[l + 1..lt] < v// arr[lt + 1..i) == vswap(arr,i,lt + 1);i ++;lt ++;}else if (arr[i] > v) {// 交换到gt - 1swap(arr,i,gt - 1);gt --;// 此处i不++,交换来的gt - 1还没有处理}else {// 此时arr[i] = vi ++;}}// lt落在最后一个 < v的索引处swap(arr,l,lt);// arr[l..lt - 1] < vquickSortInternal3(arr,l,lt - 1);// arr[gt..r] > vquickSortInternal3(arr,gt,r);}public static void main(String[] args) {int[] arr2={9,1,5,8,3,7,4,6,2};quickSort3(arr2);System.out.println(Arrays.toString(arr2));}
}

十大经典排序算法(冒泡、选择、插入、希尔、快排..........)相关推荐

  1. 十大经典排序算法之选择排序及其优化

    一.简单选择排序 1.基本思想: 在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换: 第二次遍历n-2个数,找到最小的数值与第二个元素交换: ... 第n-1次遍历,找到最 ...

  2. 【十大经典排序算法】java实现--希尔排序(4)

    希尔排序概述: 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序. 选择一个增量序列 t1,t2, ...

  3. 十大经典排序算法详解(一)冒泡排序,选择排序,插入排序

    养成习惯,先赞后看!!! 你的点赞与关注真的对我非常有帮助.如果可以的话,动动手指,一键三连吧!!! 目录 1.算法的评判标准 2.排序算法的分类 3.十大经典排序算法-冒泡排序,选择排序,插入排序 ...

  4. 十大经典排序算法总结(够兄弟们喝一壶的)

    Ⅰ.十大经典排序算法之插入排序及其二分优化:https://blog.csdn.net/Kevinnsm/article/details/114403557 Ⅱ.十大经典排序算法之冒泡排序及其优化:h ...

  5. 十大经典排序算法详解(三)-堆排序,计数排序,桶排序,基数排序

    养成习惯,先赞后看!!! 你的点赞与关注真的对我非常有帮助.如果可以的话,动动手指,一键三连吧!!! 十大经典排序算法-堆排序,计数排序,桶排序,基数排序 前言 这是十大经典排序算法详解的最后一篇了. ...

  6. 【完整可运行源码+GIF动画演示】十大经典排序算法系列——冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序

    以前也零零碎碎发过一些排序算法,但总是不系统, 这次彻底的对排序系列做了一个整体的规划, 小伙伴们快快mark哦~ [GIF动画+完整可运行源代码]C++实现 冒泡排序--十大经典排序算法之一 [GI ...

  7. 【GIF动画+完整可运行源代码】C++实现 选择排序——十大经典排序算法之二

    十大经典排序算法系列博客-->传送门 选择排序是一种简单直观的排序算法,首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的 ...

  8. 冒泡和快速排序的时间复杂度_十大经典排序算法——快速排序

    目录 1.1.排序分类 1.2.排序的定义: 对一序列对象根据某个关键字进行排序. 1.3.术语说明 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面. 不稳定:如果a原本在b的前面,而a ...

  9. 十大经典排序算法-选择排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

  10. 数据结构十大经典排序算法--Python

    十大经典排序算法 (java实现看这个)https://program.blog.csdn.net/article/details/83785159 名词解释: 1.冒泡排序 2.选择排序 3.插入排 ...

最新文章

  1. 理解ResNet结构与TensorFlow代码分析
  2. ORA-01940:cannot drop a user that is currently connected
  3. 【转载保存】mysql不设置主键使用自增长ID方法
  4. Node.js入门 - 回调函数
  5. Shell——传递参数
  6. 资源放送丨《Oracle中为什么没有Double Write?Oracle支持原子写吗?》PPT视频
  7. mysql主从北_mysql主从复制(超简单)
  8. Android View移动的六种方法
  9. PASCAL-VOC2012 数据集介绍 及 制作同格式数据
  10. JavaScript 详解:为什么写好的代码非常重要
  11. AlertDialog源码解析之一
  12. SSLOJ 1298.网站计划
  13. Linux下卸载miniconda3(Anaconda类系)
  14. Matlab线型、标记、颜色表示代码
  15. visio怎么画球_cad怎么画装配图
  16. 数据挖掘--数据流挖掘
  17. 解决浏览器访问GitHub响应时间长,速度慢的问题
  18. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: FUNCTION wm.concat does not exist
  19. 退出mysql控制台与退出mysql
  20. Qt图形视图框架详解-安晓辉-专题视频课程

热门文章

  1. 网易游戏大咖专访丨《第五人格》主创团队畅谈游戏研发修炼记
  2. Ribbon界面开发:如何创建Ribbon样式的应用程序框架
  3. 注册岩土工程师计算机专业的能考吗,岩土工程师报考条件
  4. ajax返回String类型导致的flowplayer报错p.replace is not a function问题
  5. react代码编辑器 react-ace
  6. 利用Java编写自动关机程序(包括输入、输出、控制电脑自动关机)
  7. 周末DIY,三花聚顶,练就静音功夫!
  8. 【税务基础知识】--很实用的常识
  9. kali初学——nmap扫描
  10. 第一章-网络安全行业