码迷,mamicode.com
首页 > 编程语言 > 详细

8大排序算法图文讲解

时间:2017-09-30 16:15:57      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:第一个   基于   cts   csdn   错误   break   除了   子序列   static   

排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。

我们这里说说八大排序就是内部排序。

技术分享

    

    当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序序。

   快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;

算法一:插入排序

 

技术分享

插入排序示意图

插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法步骤:

1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

代码实现:

 1 public class InsertSort {
 2     
 3     public static void sort(int[] num){
 4         int i,j,min,temp;
 5         for(i=0;i<num.length;i++){
 6             min=i;//将当前下标定义为最小值下标
 7             for(j=i+1;j<num.length;j++){
 8                 if (num[min]>num[j]) {
 9                     min=j;//如果有小于当前最小值的关键字,将此关键字的下标赋值给min
10                 }
11             }
12             if (i!=min) {//若min不等于i,说明上面相互比较的为true,即有最小值,交换
13                 temp=num[i];
14                 num[i]=num[min];
15                 num[min]=temp;
16             }
17         }
18         for (int k : num) {
19             System.out.println(k);
20         }
21         
22     }
23     
24     
25     public static void main(String[] args) {
26         // TODO 自动生成的方法存根
27         int[] num={5,2,4,6,8,9,7,1,3,0};
28         sort(num);
29     }
30 }

 算法二:希尔排序

技术分享

希尔排序示意图

 技术分享

 

给定实例的shell排序的排序过程
假设待排序文件有10个记录,其关键字分别是:
49,38,65,97,76,13,27,49,55,04。
增量序列的取值依次为:
5,3,1

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  • 插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率
  • 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位

希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

算法步骤:

1)选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;

2)按增量序列个数k,对序列进行k 趟排序;

3)每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

代码实现:

 1 public class ShellSort {
 2     //希尔排序
 3     public static void sort(int[] a) {
 4         // 希尔排序
 5         int d = a.length;
 6         while (true) {
 7             d = d / 2;
 8             for (int x = 0; x < d; x++) {
 9                 for (int i = x + d; i < a.length; i = i + d) {
10                     int temp = a[i];
11                     int j;
12                     for (j = i - d; j >= 0 && a[j] > temp; j = j - d) {
13                         a[j + d] = a[j];
14                     }
15                     a[j + d] = temp;
16                 }
17             }
18             if (d == 1) {
19                 break;
20             }
21         }
22         
23         for (int k : a) {
24             System.out.println(k);
25         }
26     }
27 
28     public static void main(String[] args) {
29         // TODO Auto-generated method stub
30         int[] a = { 5, 2, 4, 6, 8, 9, 7, 1, 3, 0 };
31         // int[]a={49,38,65,97,76,13,27,49,78,34,12,64,1};
32         sort(a);
33     }
34 
35 }

算法三:选择排序

技术分享

选择排序示意图

选择排序(Selection sort)也是一种简单直观的排序算法。

算法步骤:

1)首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

2)再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

3)重复第二步,直到所有元素均排序完毕。

代码实现:

 1 /**
 2  * 选择一个min做基准和其他的数据相互比较,如果比较的数大则把当前的数的赋值给min
 3  * 以此类推
 4  * @author Administrator
 5  *
 6  */
 7 public class SelectSort {
 8     //简单选择排序,选择一个min做基准和其他的数据相互比较
 9     public static void sort(int[] num){
10         int i,j,min,temp;
11         for(i=0;i<num.length;i++){
12             min=i;//将当前下标定义为最小值下标
13             for(j=i+1;j<num.length;j++){
14                 if (num[min]>num[j]) {
15                     min=j;//如果有小于当前最小值的关键字,将此关键字的下标赋值给min
16                 }
17             }
18             if (i!=min) {//若min不等于i,说明上面相互比较的为true,即有最小值,交换
19                 temp=num[i];
20                 num[i]=num[min];
21                 num[min]=temp;
22             }
23         }
24         for (int k : num) {
25             System.out.println(k);
26         }
27         
28     }
29     
30     public static void main(String args[]){
31         int[] num={5,2,4,6,8,9,7,1,3,0};
32         sort(num);
33 
34     }
35 }

 算法四:冒泡排序

技术分享

冒泡排序示意图

 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法步骤:

1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。

2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

3)针对所有的元素重复以上的步骤,除了最后一个。

4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

代码实现:

 1 /**
 2  * 相邻数据两两比较,大的排上面,小的排下面 第一次可排出最小的值
 3  * 第二次排出第二小的值
 4  * 第三次排出第三小的值
 5  * 以此类推排出顺序
 6  * @author Administrator
 7  *
 8  */
 9 public class BubbleSort {
10     
11     //初级版
12     public static void sort1(int[] num){
13         int i,j,temp;
14         for(i=0;i<num.length;i++){
15             for(j=i+1;j<num.length;j++){
16                 if (num[i]>num[j]) {
17                     temp=num[i];
18                     num[i]=num[j];
19                     num[j]=temp;
20                 }
21             }
22         }
23         for (int k : num) {
24             System.out.println(k);
25         }
26         
27     }
28     //中级版
29     public static void sort2(int[] num){
30         int i,j,temp;
31         for(i=0;i<num.length;i++){
32             for(j=num.length-1;j>i;j--){
33                 if (num[j-1]>num[j]) {
34                     temp=num[j-1];
35                     num[j-1]=num[j];
36                     num[j]=temp;
37                 }
38             }
39         }
40         for (int k : num) {
41             System.out.println(k);
42         }
43         
44     }
45     //终极版
46     public static void sort3(int[] num){
47         int i,j,temp;
48         boolean flag=true;
49         for(i=0;i<num.length&&flag;i++){
50             flag=false;
51             for(j=num.length-1;j>i;j--){
52                 if (num[j-1]>num[j]) {
53                     temp=num[j-1];
54                     num[j-1]=num[j];
55                     num[j]=temp;
56                     flag=true;
57                 }
58             }
59         }
60         for (int k : num) {
61             System.out.println(k);
62         }
63         
64     }
65     
66     
67     public static void main(String args[]){
68         int[] num={5,2,4,6,8,9,7,1,3,0};
69 //        sort1(num);
70 //        sort2(num);
71         sort3(num);
72     }
73     
74 }

 算法五:归并排序

技术分享

归并排序示意图

归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

分而治之

技术分享

   可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n。

合并相邻有序子序列

  再来看看阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。

技术分享

技术分享

代码实现

技术分享
package sortdemo;

import java.util.Arrays;

/**
 * Created by chengxiao on 2016/12/8.
 */
public class MergeSort {
    public static void main(String []args){
        int []arr = {9,8,7,6,5,4,3,2,1};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void sort(int []arr){
        int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        sort(arr,0,arr.length-1,temp);
    }
    private static void sort(int[] arr,int left,int right,int []temp){
        if(left<right){
            int mid = (left+right)/2;
            sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
            sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
            merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
        }
    }
    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i = left;//左序列指针
        int j = mid+1;//右序列指针
        int t = 0;//临时数组指针
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t++] = arr[i++];
            }else {
                temp[t++] = arr[j++];
            }
        }
        while(i<=mid){//将左边剩余元素填充进temp中
            temp[t++] = arr[i++];
        }
        while(j<=right){//将右序列剩余元素填充进temp中
            temp[t++] = arr[j++];
        }
        t = 0;
        //将temp中的元素全部拷贝到原数组中
        while(left <= right){
            arr[left++] = temp[t++];
        }
    }
}
技术分享

执行结果

[1, 2, 3, 4, 5, 6, 7, 8, 9]

最后

  归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差。java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。从上文的图中可看出,每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。

 

8大排序算法图文讲解

标签:第一个   基于   cts   csdn   错误   break   除了   子序列   static   

原文地址:http://www.cnblogs.com/linjiaxin/p/7615196.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!