十大排序算法及代码解析

    作为一个程序设计人员,必须要懂算法和数据结构,这是每个毕业生必备的知识,最近在复习排序算法,进行全部的总结和介绍,但愿可以给学习排序算法的有所帮助,其中会有java和JavaScript的代码进行介绍。

一、十大排序算法

   首先从一张大图来了解这十种排序算法的基本认识和比较,主要从时间复杂度和空间复杂度来介绍,图片是网上找的,不是自己做的。

               

1.冒泡排序算法

   1).算法简介:看名字就能体会到他的原理,冒泡算法即冒泡泡,常识知道水中最小的泡泡会冒到最顶端,即总在这个算法中最小的数浮在上面。

  2).基本思想:每次比较两个相邻的元素,如果它们的顺序错误就把它们交换过来,但是这个排序要走访所有的元素。最差的可能就是逆序(但可以写一个逆序方法解决),最好的情况就是顺序排好(不用排序)。

 3).算法描述:

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

     2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

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

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

 4).举例说明:对{12,25,8,36,9}这5个数从大到小排序。

     首先明确,从大到小,就是最小的在最后面。然后进行排序演示:首先比较最前面的两个数,12和25,12<25,即12在25的后面,第一次排序后为: 25, 2,8, 36, 9,第二次比较: 2<8,顺序不正确,进行交换,得到第二次排序: 25, 8, 2, 36, 9,

第三次比较:2<36,则2和36要交换顺序,得到第三次排序: 25, 8,36, 2,9 第四次比较:2<9,要交换顺序,得到排序25, 8,36, 9, 2。经过 4 次比较后我们发现最小的一个数已经就位。这就是走过一趟排序,然后进行重复比较,直到最后的顺序正确。

  5).动图演示:(图片转载网上博客)

   

6).代码:

     java代码:

package 排序算法;


public class Maopao {
	 public static void main(String[] args) {
		int [] a={3,8,25,6,16,98,25,64,12,0};//定义一个整型的数组
	    int t;
	    System.out.println("排序前的数组顺序");//输出提示语句
	      for(int i=0;i<a.length ;i++)//for循环遍历数组
	    	System.out.print(a[i]+",");
	         System.out.println();//进行换行语句控制
	    for(int i=0;i<a.length-1;i++)//外层循环控制排序趟数
	          {
			     for(int j=0;j<a.length-1-i;j++)//内层循环控制每一趟排序多少次
			       {
				       if(a[j]<a[j+1]) 
				       { 
					        t=a[j];
					        a[j]=a[j+1];
					        a[j+1]=t; 
					    }
			            }
	           }
	      System.out.println("排序后的数组顺序");
	      System.out.print("[");
	            for(int order:a )//用增强for来遍历数组,也可以用常规for循环
		    	   System.out.print(order+",");
	       System.out.println("]");
	 } 
}
	 public static void main(String[] args) {
		int [] a={3,8,25,6,16,98,25,64,12,0};//定义一个整型的数组
	    int t;
	    System.out.println("排序前的数组顺序");//输出提示语句
	      for(int i=0;i<a.length ;i++)//for循环遍历数组
	    	System.out.print(a[i]+",");
	         System.out.println();//进行换行语句控制
	    for(int i=0;i<a.length-1;i++)//外层循环控制排序趟数
	          {
			     for(int j=0;j<a.length-1-i;j++)//内层循环控制每一趟排序多少次
			       {
				       if(a[j]<a[j+1]) 
				       { 
					        t=a[j];
					        a[j]=a[j+1];
					        a[j+1]=t; 
					    }
			            }
	           }
	      System.out.println("排序后的数组顺序");
	      System.out.print("[");
	            for(int order:a )//用增强for来遍历数组,也可以用常规for循环
		    	   System.out.print(order+",");
	       System.out.println("]");
	 } 
}
运行结果: 

  

优化一:自己可以在控制台中输入任意大小的数组元素进行排序,不在是自定义的数组:

package 排序算法;

import java.util.Arrays;
import java.util.Scanner;

public class Maopao2 {
  public static void main(String[] args) {
	  Scanner sc=new Scanner(System.in);
	  System.out.println("请输入一个你想要排序的数组的大小:");
	     while(sc.hasNext())
	      {  //循环读入键入的数字存入数组中
	         int m=sc.nextInt();
	         //System.out.println(m);
	         int[] number=new int[m];
	         for(int i=0;i<m;i++)//循环读入一个数组的元素
	         {
	             number[i]=sc.nextInt();
	         }
	        // Arrays.sort(number);
	         System.out.println("你输入的数组是:");
	         System.out.println(Arrays.toString(number));
	     
	         int t;
	         for(int i=0;i<number.length-1;i++)//外层循环控制排序趟数
	          {
			     for(int j=0;j<number.length-1-i;j++)//内层循环控制每一趟排序多少次
			       {
				       if(number[j]<number[j+1]) 
				       { 
					        t=number[j];
					        number[j]=number[j+1];
					        number[j+1]=t; 
					    }
			            }
	           }
	      System.out.println("冒泡排序后的数组顺序");
	      System.out.print("[");
	         for(int order:number)
              	 System.out.print(order+",");
	       System.out.println("]");
  }       
  }
	    
}


运行结果如下:

    javascript代码:将代码复制粘贴到webstorm创建的js文件中就可以直接运行。

function paixu() {
    console.log("排序前的数组顺序:");
    var a=[45,67,1,5,82];/* 定义一个数组*/
    console.log(a);/*控制台输出数组*/

    (function maopao() {
        for(var i=0;i<a.length-1;i++){//外层循环控制排序趟数,有n个元素,就会有n-1趟比较
            for(var j=0;j<a.length-1-i;j++){//内层循环控制每一趟排序多少次
                if (a[j] < a[j + 1]) {
                    var tmp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = tmp;
                }
            }
        }
        console.log("冒泡排序后的顺序是:")
        console.log(a);
    })();
}
paixu();/*函数自调用*/

运行结果:

2.选择排序

 

1).算法简介:表现最稳定的算法之一,选择排序(Selection-sort)是一种简单直观的排序算法,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。

  2).基本思想:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

 3).算法描述:

     1初始状态:无序区为a[1..n],有序区为空

     2第i趟排序(i=1,2,3...n-1)开始时,当前有序区和无序区分别为a[1..i-1]和R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 a[k],将它与无序区的第1个记录a交换,使a[1..i]aR[i+1..n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区

    3n-1趟结束,数组有序化了

 4).动图演示:(图片转载网上博客)

6).代码:

 a.java代码

package 排序算法;

import java.util.Arrays;
import java.util.Scanner;

import sun.security.krb5.SCDynamicStoreConfig;

public class SelectionSort {
	//选择排序法
	public static void main(String[] args) {
		Scanner  sc=new Scanner(System.in);
		System.out.println("请输入你想排序的数组大小:");
		while(sc.hasNext()){
			int m=sc.nextInt();
			int a[]=new int[m];
			for(int x=0;x<m;x++){
				a[x]=sc.nextInt();
			}
			System.out.println("你输入的数组是:");
			System.out.println(Arrays.toString(a));
			
			for(int i=0;i<a.length-1;i++){
				int minindex=i;
				int t;
				for(int j=i+1;j<a.length;j++){
					if(a[j]<a[minindex]){//循环寻找最小值
						minindex=j; //保存最小值的索引
					}
				}
				t=a[i];
				a[i]=a[minindex];
				a[minindex]=t;
				
			}
			 System.out.println("选择排序后的数组顺序");
		      System.out.print("[");
			for(int order:a)
			   System.out.print(+order+",");
			   System.out.print("]");
		
			
		}
				
	}

}

 b. JavaScript的代码:

function SelectSort(a) {
    var temp, maxindex;
    var len = a.length;
    console.time('选择排序耗时');
    for (var i = 0; i < len - 1; i++) {//找到最大值的那个索引
        maxindex = i;
        for (var j = i+1; j <len; j++) {//从i后的无序找最大值,进行排序
            if (a[j] > a[maxindex]) {
                maxindex = j;  //把最大值的索引给j
            }
        }
                temp = a[i];
                a[i] = a[maxindex];
                a[maxindex] = temp;

    }
    console.timeEnd('选择排序耗时');
    return a;

}

var a=[3,42,38,5,47,15,36,26,27,50,48,98,20];
console.log('你输入的数组顺序是:');
console.log(a);
console.log('选择排序的数组顺序:');
console.log(SelectSort(a));

运行结果:

你输入的数组顺序是:
[ 3, 42, 38, 5, 47, 15, 36, 26, 27, 50, 48, 98, 20 ]
选择排序的数组顺序:
选择排序耗时: 0.526ms
[ 98, 50, 48, 47, 42, 38, 36, 27, 26, 20, 15, 5, 3 ]

3.插入排序

  1).算法简介:书上和好多博客上简单的解释就像和打扑克一样把牌插入,插入的方法就是按照某种方式把他放到合适的位置,

简单的排序中,就是把它放在两个数的中间,实现顺序的正确。

  2).基本思想:它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

 3).算法描述:

 

  • 1>.从第一个元素开始,这个元素可以默认认为已经被排序;
  • 2>.取出下一个元素,在已经排序的元素序列中从后向前扫描;
  • 3>.如果该元素(已排序)大于新元素,将该元素移到下一位置;
  • 4>.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  • 5>.将新元素插入到该位置后;
  • 6>.重复步骤2~5。

4).动图演示:(图片转载网上博客)

5).代码:装载

java代码:

package com.test.insertsort;
/**
 * 插入排序算法:
 * 1、以数组的某一位作为分隔位,比如index=1,假设左面的都是有序的.
 * 
 * 2、将index位的数据拿出来,放到临时变量里,这时index位置就空出来了.
 * 
 * 3、从leftindex=index-1开始将左面的数据与当前index位的数据(即temp)进行比较,如果array[leftindex]>temp,
 * 则将array[leftindex]后移一位,即array[leftindex+1]=array[leftindex],此时leftindex就空出来了.
 * 
 * 4、再用index-2(即leftindex=leftindex-1)位的数据和temp比,重复步骤3,
 * 直到找到<=temp的数据或者比到了最左面(说明temp最小),停止比较,将temp放在当前空的位置上.
 * 
 * 5、index向后挪1,即index=index+1,temp=array[index],重复步骤2-4,直到index=array.length,排序结束,
 * 此时数组中的数据即为从小到大的顺序.
 * 
 * @author bjh
 *
 */
public class InsertSort {
    private int[] array;
    private int length;
    
    public InsertSort(int[] array){
        this.array = array;
        this.length = array.length;
    }
    
    public void display(){        
        for(int a: array){
            System.out.print(a+" ");
        }
        System.out.println();
    }
    
    /**
     * 插入排序方法
     */
    public void doInsertSort(){
        for(int index = 1; index<length; index++){//外层向右的index,即作为比较对象的数据的index
            int temp = array[index];//用作比较的数据
            int leftindex = index-1;
            while(leftindex>=0 && array[leftindex]>temp){//当比到最左边或者遇到比temp小的数据时,结束循环
                array[leftindex+1] = array[leftindex];
                leftindex--;
            }
            array[leftindex+1] = temp;//把temp放到空位上
        }
    }
    
    public static void main(String[] args){
        int[] array = {38,65,97,76,13,27,49};
        InsertSort is = new InsertSort(array);
        System.out.println("排序前的数据为:");
        is.display();
        is.doInsertSort();
        System.out.println("排序后的数据为:");
        is.display();
    }
}

JavaScript代码:

function insertsort() {

    var a=[ 3, 42, 38, 5, 47, 15, 36, 26, 27, 50, 48, 98, 20 ];
    console.log('当前数组元素:');
    console.log(a);
    var len=a.length;  //定义数组的长度
    var current,preindex;  //定义两个索引
    console.time('插入排序用时');  //计时器,用来计标记这个算法的所用时间
    (function insert() {
        for(var i=0;i<len;i++){   //遍历所有的数组元素,每次都拿出一个元素,进行插入比较
            preindex=i-1;
            current=a[i];

          while(preindex>=0&& a[preindex]>current){  //插入时的比较,最后一个元素直到所有的元素结束
              a[preindex+1]=a[preindex];
              preindex--;
          }

            a[preindex+1] = current;
        }
        console.log('插入排序后的数组元素:');
        console.log(a);
        console.timeEnd('插入排序用时');
    })();
}


insertsort();

运算结果:

当前数组元素:
[ 3, 42, 38, 5, 47, 15, 36, 26, 27, 50, 48, 98, 20 ]
插入排序后的数组元素:
[ 3, 5, 15, 20, 26, 27, 36, 38, 42, 47, 48, 50, 98 ]
插入排序用时: 0.619ms

4.希尔排序

  1).算法简介:它是简单插入排序的更进一步改进,这种算法和插入排序算法不同之处就是首先比较距离比较远的元素。

  2).基本思想:希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。先将整个待排序的记录分成若干个子序列,然后进行直接插入排序,待整个序列中的记录有了基本有序时,在对全体序列做一次插入排序。

 3).算法描述:

  1).先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组,将距离为d1的倍数的记录放在同一组中,在

各个组中进行插入排序

  2).然后取第二个增量d2,(d2<d1),重复(1)分组和排序工作,

  3).以此类推,直至所取的增量di=1(di<di-1<........d1),即所有的记录放在同一组中进行直接插入排序。

  4).注意,一般d1=n/2;d(i+1)=di/2;如果结果是偶数,加1让他变成奇数来进行分组

4).举例说明:

    一组记录[72,58,94,23,5]共有5个记录,进行希尔排序的演示:

   1.先进行分组 d1=n/2=5/2=3 ,以3为距离进行分组: 就会有[72,23],[58,5][94]这三个基本组;

   2.在各组中进行插入排序后,得到新的记录[23,5,94,72,58],

   3.在进行第二次分组: d2=d1/2=1(取奇数),结果距离为1,所以分组结束,进行最后的直接插入排序

   4.通过上述插入排序的方法得到最终的结果是[5,23,58,72,94]

5)代码演示:

 java代码:

public static void shellSort(int[] a){
        double gap = a.length;//增量长度
        int dk,sentinel,k;
        while(true){
            gap = (int)Math.ceil(gap/2);//逐渐减小增量长度
            dk = (int)gap;//确定增量长度 
            for(int i=0;i<dk;i++){
                //用增量将序列分割,分别进行直接插入排序。随着增量变小为1,最后整体进行直接插入排序
                for(int j=i+dk;j<a.length;j = j+dk){
                    k = j-dk;
                    sentinel = a[j];
                    while(k>=0 && sentinel<a[k]){
                        a[k+dk] = a[k];
                        k = k-dk;
                    }
                    a[k+dk] = sentinel;
                }
            }
            //当dk为1的时候,整体进行直接插入排序  
            if(dk==1){
                break;
            }
        }
    }

JavaScript代码:

//希尔排序算法:
/*
* 1.进行对所有的记录的分组
* 2.对分组的记录进行直接插入排序
* 3.直到所有的分组结束,即di=1,对最后的记录进行直接的插入排序
* */

 function shellsort(arr) {
     var len = arr.length;
     var gap=1;
     var temp;
     console.log('你定义的的数组是:');
     console.log(arr);
     console.time('希尔排序时间');
     while (gap < len / 2) {  //动态定义分组间隔
         gap = gap * 2 + 1;
     }
     for (gap; gap > 0; gap = Math.floor(gap/2))
         {//排序的趟数,对所有的记录进行分组,直到分组的距离为1为止
             for (var i = gap; i < len; i++)
             { //对分组类中的记录进行插入排序
                 temp = arr[i];
                 for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
                     arr[j + gap] = arr[j];
                 }
                 arr[j + gap] = temp;
             }
         }

           console.timeEnd('希尔排序时间');
            console.log('希尔排序的数组')
           return arr;

 }

var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(shellsort(arr));

运行结果:

你定义的的数组是:
[ 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 ]
希尔排序时间: 0.592ms
希尔排序的数组

[ 2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50 ]

5.归并排序

  1).算法简介:和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。

  2).基本思想:归并排序是建立在归并操作上的一种有效的排序算法,归并排序是将两个或两个以上的有序子表合并成一个新的有序表,初始化时,把含有n个记录的带排序的序列看做是n个长度都为1的有序子表组成,将他们两两归并,得到长度为2的若干有序表,再对他们合并,直到得到最后的正确排序。

 3).算法描述:

   1.先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组,将距离为d1的倍数的记录放在同一组中,在

各个组中进行插入排序

   2.然后取第二个增量d2,(d2<d1),重复(1)分组和排序工作,

   3.以此类推,直至所取的增量di=1(di<di-1<........d1),即所有的记录放在同一组中进行直接插入排序。

   4.注意,一般d1=n/2;d(i+1)=di/2;如果结果是偶数,加1让他变成奇数来进行分组

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值