黑马程序员技术交流社区

标题: 排序浅谈 [打印本页]

作者: Deathfish    时间: 2015-6-11 00:09
标题: 排序浅谈
本帖最后由 Deathfish 于 2015-6-11 00:09 编辑

排序作为计算机运行中的一种基本操作,常常作为编程入门示例出现在各种教材上。
下面将介绍几种不同性能的排序算法,希望大家能通过这些代码,能够体会到编程艺术的美妙。
一下示例就通过排列数组展示。
在各种排序算法中,最容易让人理解的,莫过于选择排序法
通过遍历数组中个各个元素,找出最大(最小)值,再置于数组最后(最前),从而对数组进行排序。

另一种大家都非常熟悉的是冒泡排序法
通过将数组中两相邻值做比较,前值大于后值,则将前后值位置进行替换。



接着就是相对新能较佳,内存消耗及速度性能均不错的快速排序法
选取数组中的一个值作为基准值,小于其值的置于数组前方,大于等于其值的置于数组后方,再对分割出的两个子数组做相同规则的排序



最后向大家介绍的是哈希排序的原理
将整数按位数切割成不同的数字,然后按每个位数分别比较。
相关代码如下:
  1. class SortMethod{
  2. /**
  3.         打印一个数组
  4. */
  5.         public static void listPriter(int[] arr){
  6.                 for(int e: arr){
  7.                         System.out.println(e);
  8.                 }
  9.         }

  10. /**
  11.         生成一个不含重复元素的从(0-n)的随机int数组
  12. */
  13.         public static int [] randList0 (int n)
  14.         {
  15.                 int [] randNum = new int [n];
  16.                 int [] unUsed = new int [n];
  17.                 for (int u = 0; u < n; u++)
  18.                 {
  19.                         unUsed[u] = u+1;
  20.                 }
  21.                 for (int i = 0; i < n; i++)
  22.                 {
  23.                         double positionDouble =  Math.random() * (n-1-i);
  24.                         int position = (int) positionDouble;
  25.                         randNum[i] = unUsed[position];
  26.                         unUsed[position] = unUsed[n-1-i];
  27.                 }
  28.                 return randNum;
  29.         }
  30. /**
  31.         生成一个包含重复元素的从(0-n)的随机int数组
  32. */
  33.         public static int [] randList1 (int n)
  34.         {
  35.                 int [] randNum = new int[n];
  36.                 // Random r = new Random();
  37.                 for (int i = 0; i < n; i++)
  38.                 {
  39.                         double numDouble = Math.random() * (n-1-i);
  40.                         int num = (int) numDouble;
  41.                         randNum[i] = num;
  42.                 }
  43.                 return randNum;
  44.         }
  45. /**
  46.         选择排序法
  47.         时间复杂度为O(N^2)
  48. */
  49.         public static int [] selectionSort(int [] unSortedArr){
  50.                 int [] sortedArr = unSortedArr;
  51.                 //外层循环遍历数组各元素
  52.                 for (int i = 0; i < sortedArr.length ;i++){
  53.                         int min =i;
  54.                         //内层循环将外层循环所遍历到的元素和数组中其它为排序的元素进行大小比较
  55.                         for(int j =i ; j< sortedArr.length;j ++){
  56.                                 if (sortedArr[min] > sortedArr[j]){
  57.                                         min = j;
  58.                                 }
  59.                         }
  60.                         //比较后得出未排序数组中的最小值,将其写入到排序数组的前部
  61.                         int temp = sortedArr[i];
  62.                         sortedArr[i] = sortedArr[min];
  63.                         sortedArr[min] = temp;
  64.                 }
  65.                 return sortedArr;
  66.         }
  67. /**
  68.         冒泡排序法
  69.         时间复杂度为O(N^2)
  70. */
  71.         public static int [] bubbleSort(int [] unSortedArr){
  72.         //外层循环遍历数组各元素
  73.                 for (int i = 0; i < unSortedArr.length ; i++ ){
  74.                         //内层循环将外层循环所遍历到的元素和其相邻的后一位数组进行大小比较
  75.                         for(int j = 0; j < unSortedArr.length-i-1; j++){
  76.                                 if(unSortedArr[j]>unSortedArr[j+1]){
  77.                                         //比较后,相对较大的元素置于相对靠后的位置
  78.                                         int temp = unSortedArr[j];
  79.                                         unSortedArr[j] = unSortedArr[j+1];
  80.                                         unSortedArr[j+1] = temp;
  81.                                 }
  82.                         }
  83.                 }
  84.                 return unSortedArr;
  85.         }
  86. /**
  87.         快速排序法
  88.         时间复杂度为O(NlogN)
  89. */
  90.         public static int [] QuickSort(int [] unSortedArr, int startIndex, int endIndex){
  91.                 //先选取基准值为最后一个元素的大小。同时设置数组排序的起始及终止角标
  92.                 int pivot = endIndex;
  93.                 int l = startIndex;
  94.                 int h = endIndex;
  95.                 while(l<h){
  96.                         //遍历时末端角标往前移一位
  97.                         h--;
  98.                         //通过while循环从数组后端 h 至数组前端 l 遍历,若被遍历的元素小于基准值,
  99.                         // 则将其移动到数组前端,同时前端 l 角标增一位。
  100.                         while(l<h&&unSortedArr[pivot]>unSortedArr[h]){
  101.                                 int temp0 = unSortedArr[l];
  102.                                 unSortedArr[l] = unSortedArr[h];
  103.                                 unSortedArr[h] = temp0;
  104.                                 l++;
  105.                         }
  106.                 }
  107.                 // 循环遍历完后 l=h ,还剩下角标为 l 的元素未和基准值比对过大小。
  108.                 // 同时基准值位于数组最末端,这时我们需要将它移动到数组中间。
  109.                 if(unSortedArr[pivot]>unSortedArr[l]){
  110.                         int temp1 = unSortedArr[l+1];
  111.                         unSortedArr[l+1] = unSortedArr[pivot];
  112.                         unSortedArr[pivot] = temp1;
  113.                         pivot = l+1;
  114.                 }else{
  115.                         int temp2 = unSortedArr[l];
  116.                         unSortedArr[l] = unSortedArr[pivot];
  117.                         unSortedArr[pivot] = temp2;
  118.                         pivot = l;
  119.                 }
  120.                 // 最后将大于基准值与小于基准值的两个数组部分通过递归进行传递排序
  121.                 if(pivot-1>startIndex)
  122.                         QuickSort(unSortedArr,startIndex,pivot-1);
  123.                 if(endIndex>pivot+1)
  124.                         QuickSort(unSortedArr,pivot+1,endIndex);
  125.                 return unSortedArr;
  126.         }
  127. /**
  128.         哈希排序法(模拟)
  129.         先找出数组中的最大值和最小值,创建一个max-min长度的临时寄存数组,
  130.         遍历待排序数组,将遍历到的数组元素放入下标与其值相等的临时寄存数组中(临时寄存数组对应下标的元素的值+1),
  131.         待遍历完原数组后,对临时寄存数组进行遍历。若数组中值为n,则说明原数组中有n个大小为 数组下标+min的元素。
  132.         将这些元素按顺序添加入一个新数组中,这个新数组就是一个排序好的数组。
  133.         时间复杂度为O(N)
  134. */
  135.         public static int [] hashSort(int [] unSortedArr){
  136.                 int max = unSortedArr[0];
  137.                 int min = unSortedArr[0];
  138.                 int [] sortedArr = new int [unSortedArr.length];
  139.                 // 通过for循环找到最大值和最小值
  140.                 for (int i =0; i< unSortedArr.length; i++){
  141.                         if(unSortedArr[i]>max)
  142.                                 max = unSortedArr[i];
  143.                         if(unSortedArr[i]<min)
  144.                                 min = unSortedArr[i];
  145.                 }
  146.                 // 定义储存元素的临时数组,数组的大小为最大值至最小值的范围
  147.                 int [] sortTemp = new int[max-min+1];
  148.                 // 通过for循环遍历未排序的原数组,将遍历到的数组元素放入下标与其值相等的临时寄存数组中
  149.                 for(int i = 0; i<unSortedArr.length; i++){
  150.                         sortTemp[unSortedArr[i]-min] += 1;
  151.                 }
  152.                 //定义数组指针
  153.                 int index = 0;
  154.                 //通过for循环将临时数组中的元素顺序取出,存入新的数组中,既是排序好的数组
  155.                 for(int i = 0; i<sortTemp.length; i++){
  156.                         for(int j = 0; j<sortTemp[i]; j++){
  157.                                 sortedArr[index] = i+min;
  158.                                 index++;
  159.                         }
  160.                 }
  161.                 return sortedArr;
  162.         }
  163. }
复制代码


对于不同排序算法的运行效率结果如下:











测试代码见一楼。





100.png (21.25 KB, 下载次数: 14)

100.png

10000.png (21.8 KB, 下载次数: 14)

10000.png

100000.png (22.73 KB, 下载次数: 13)

100000.png

10000000.png (16.58 KB, 下载次数: 14)

10000000.png

QQ Photo20150610233004.jpg (89.19 KB, 下载次数: 11)

QQ Photo20150610233004.jpg

作者: Deathfish    时间: 2015-6-11 00:09

  1. public class SortMethodTest{
  2.         public static void main(String [] args){
  3.        
  4.                 int n = 10000000;
  5.                 long timeStart,timeEnd ;
  6.                
  7.                 int[] randomList = SortMethod.randList1(n);
  8.                 System.out.println("无序数组的大小为:"+n);

  9.                
  10.                 timeStart = System.currentTimeMillis();
  11.                 int [] sortedList0 = SortMethod.selectionSort(randomList);
  12.                 timeEnd = System.currentTimeMillis();
  13.                 // SortMethod.listPriter(sortedList0);
  14.                 System.out.println("selectionSort选择排序 排序时间 time : " + (timeEnd - timeStart) + "毫秒 ");
  15.                
  16.                 timeStart = System.currentTimeMillis();
  17.                 int [] sortedList1 = SortMethod.bubbleSort(randomList);
  18.                 timeEnd = System.currentTimeMillis();
  19.                 // SortMethod.listPriter(sortedList1);
  20.                 System.out.println("bubbleSort冒泡排序 排序时间 time : " + (timeEnd - timeStart) + "毫秒 ");
  21.                
  22.                 timeStart = System.currentTimeMillis();
  23.                 int [] sortedList2 = SortMethod.QuickSort(randomList,0,randomList.length-1);
  24.                 timeEnd = System.currentTimeMillis();
  25.                 // SortMethod.listPriter(sortedList2);
  26.                 System.out.println("QuickSort快速排序 排序时间 time : " + (timeEnd - timeStart) + "毫秒 ");
  27.                
  28.                 timeStart = System.currentTimeMillis();
  29.                 int [] sortedList3 = SortMethod.hashSort(randomList);
  30.                 timeEnd = System.currentTimeMillis();
  31.                 // SortMethod.listPriter(sortedList3);
  32.                 System.out.println("hashSort哈希排序 排序时间 time : " + (timeEnd - timeStart) + "毫秒 ");
  33.         }
  34. }
复制代码



作者: 小骆驼    时间: 2015-6-11 11:03
赞一个,不错,好好学习下
作者: DAN66    时间: 2015-6-11 23:28
赞一个
作者: q757571446    时间: 2015-6-11 23:34
赞一个,好帖子长见识了/

作者: 集体烧书    时间: 2015-7-7 16:55
林宏大神,膜拜啊




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2