java 选择排序方法原理_【排序算法】——冒泡排序、选择排序、插入排序、Shell排序等排序原理及Java实现...

本文详细介绍了排序算法的定义及评价标准,包括稳定性、时间复杂度和空间复杂度。接着讲解了五种经典的排序算法:冒泡排序、选择排序、插入排序、希尔排序和快速排序的原理及实现过程,并提供了Java代码示例。此外,还提到了归并排序这一高效的排序方法,通过分治策略将数据有序合并。这些排序算法在不同场景下有不同的效率表现,对于理解和实现排序算法具有重要价值。

排序

1.定义:

所谓排序,即是整理文件中的内容,使其按照关键字递增或递减的顺序进行排列。

输入:n个记录,n1,n2……,其对应1的关键字为k1,k2……

输出:n(i1),n(i2)……,使得k(i1)<=k(i2)……

(形象点讲就是排排坐,调座位,高在前低在后;或者低在前高在后)

2.排序算法的评价的专业术语

(1)稳定性

稳定:在排序的文件中,若存在多个关键字相同的记录,经过排序后,这些具有相同

关键字的记录之间的相对顺序不会发生改变。

不稳定:若具有相同关键字记录之间的相对次序发生改变,则成为不稳定的排序算法。

(2)复杂度

时间复杂度:一个算法执行所需消耗的时间。

空间复杂度:运行完该程序所需要的内存大小

(3)排序方式

内排序:在排序过程中,整个文件放在内存中进行处理,不涉及数据的内外存交换。

(适用于记录个数不是很多的小文件)

外排序:排序过程中要进行数据的内、外存交换。

(适用于记录个数多,不能将其一次性放入内存中的大文件)

交换排序

思想:对排序记录的关键字进行两两比较,发现次序相反时则进行交换直至没有次序相反的记录。

主要排序方法:冒泡排序、选择排序

冒泡排序

(1)算法描述:

冒泡排序是一种简单的排序,每次访问要排序的数组序列,一次比较相邻两个元素的大小,

若顺序错误就进行交换。(这个方法名的由来是小的元素慢慢“浮”在数组顶端,也可称为沉底(大的元素))

(2)算法的实现

a.比较相邻的两个元素大小,如果第一个大于第二个元素的大小就进行交换

b.对每一对相邻的元素都进行同样的操作,从第一对到最后一对,经过此步骤

最大的元素将是最后的元素。

c.针对所有的元素重复上述操作,除过最后一个。

d.重复a-c步骤,直至排序完成

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 *@Description: 排序算法3 *@Author: dyy4 */

5 public classSort {6 public static voidmain(String[] args) {7 int [] arr = new int[]{4,2,1,6,3,6,0,-5,1,1};8 bubbleSort(arr);9 //遍历打印排序后的数组![image](https://note.youdao.com/favicon.ico)

10 for(int i = 0; i < arr.length;i++){11 System.out.print(arr[i]+" ");12 }13 }14 /**

15 *冒泡排序16 * @date: 2018/8/15 11:2717 */

18 public static void bubbleSort(int[] array){19 //对数组进行临界判断

20 if(array==null||array.length==0){21 System.out.println("array is NULL");22 }23 for(int i = 0; i < array.length - 1; i++){24 //进行相邻元素额大小比较(也可循环至array.length-1,25 //循环至array.length-i-1是因为没经过一圈的排序后面的元素则就是有序的)

26 for(int j = 0;j < array.length-i-1;j++){27 if(array[j]>array[j+1]){28 swap(array,j,j+1);29 }30 }31 }32 }33 /**

34 *实现数组中两个数的交换35 * target为要交换的数组,x,y为要交换数字的下标36 * @date: 2018/8/15 11:3037 */

38 public static void swap(int[] target,int x,inty){39 int temp =target[x];40 target[x] =target[y];41 target[y] =temp;42 }43 }

View Code

9622f650feb36521fec7a2f8f8623b81.png

选择排序

(1)算法描述:选择排序是一种简单直观的排序算法。

它的工作原理是首先在未排序的序列中找到最大(小)的元素放置序列起始位置。

再从未排序序列中继续寻找元素放置已排序序列的尾部直至所有元素都有序。

(2)算法的实现:

a.初始状态:R[1……n]无序,有序数组为空

b.经过第i次扫描:R[1……i-1]有序,R[i……n]无序

c.经过n-1趟排序,为有序序列

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 *选择排序3 * @date: 2018/8/15 12:264 */

5 public static void selectSort(int[] array){6 //临界条件判断

7 if(array==null||array.length==0){8 System.out.println("array is NULL");9 }10 //做第i趟排序

11 for(int i = 0; i < array.length-1;i++){12 for(int j = i+1; j < array.length;j++){13 //选出最小的记录进行交换

14 if(array[i]>array[j]){15 swap(array,i,j);16 }17 }18 }19 }

View Code

cb2f50ecf6e0f4e9e62b467c457202c4.png

插入排序

(1)算法描述

插入排序也是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对已未排序

的序列的数据,在已经有序的序列中从后向前找并进行插入。但是在进行插入的过程中需

要不断的将已经排序好的数据进行移位操作。

(2)算法实现

a.从第一个数据开始,将该元素认为已经排序好的序列。

b.取出下一个元素,在已经排序好的元素序列中从后向前进行扫描。

c.如果该元素(排序好的元素)大于新的元素,则将该元素移动到下一个位置

d.重复步骤c,知道找到已排序好的元素小于或者等于新元素的位置

e.将新的元素插入到该位置

f.重复步骤b

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 *插入排序3 * @date: 2018/8/15 19:424 */

5 public static void insertSort(int[] array){6 //临界条件判断

7 if(array==null||array.length==0){8 System.out.println("array is null");9 }10 for(int i = 0; i < array.length;i++){11 //从下一个元素进行遍历,若新元素小于已经排序好的序列的元素进行交换

12 for(int j = i ;(j>0)&&(array[j-1]>array[j]);j--){13 swap(array,j-1,j);14 }15 }16 }

View Code

6ad15be53a3f85ed036db1006e83f52f.png

Shell排序(希尔排序)

(1)算法描述

希尔排序是插入排序的一种,其中心思想是将数据进行分组,然后对每一组

数据进行排序,在每一组数据有序后,可以利用插入排序对所有分组进行最

后一次排序。这样可以减少数据交换的次数,加快排序速度。

(2)算法实现

a.选择一个增序序列t(1),t(2)……t(n),其中t(n)=1b.按照增量序列个数k,对序列进行k此排序

c.每次排序,根据对应的增量,分为若干个长度为m的子序列,分别对子序列

进行插入排序。当增量为1时一个序列来进行处理,表长即为整个序列的长度。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /**

2 *Shell排序(希尔排序)3 * @date: 2018/8/15 20:074 */

5 public static void shellSort(int[] array){6 if(array==null||array.length==0){7 System.out.println("array is null");8 }9 //分隔集合之间的长度(第一次假设为集合长度的一半)

10 int increment = 0;11 //分隔集合之间的长度,每次为前一次的一半(最后一次为1)

12 for(increment = array.length/2;increment>0;increment = increment>>1){13 for(int i = increment;i= 0;j = j -increment){15 if(array[i]

View Code

928cc9d5764e946d797d461c1330a772.png

快速排序

(1)算法描述

快速排序是一种划分交换排序,采用分治的策略(分治法)。通过一趟排序

将待排序序列划分为两个独立的部分,其中一部分的记录的关键字均小于另

外一部分的关键字。

分法法的基本思想:将原问题分解为若干个规模更小但是结构和原问题相似

的子问题,递归地解决这些子问题,然后将这些子问题的解组合成原问题的解。

(2)算法实现

a.从数组序列中选择一个“基准元素”(此文中以每个序列第一个元素为准)

b.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准

值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,

该基准就处于数列的中间位置。这个称为分区操作

c.递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public classSort {2 public static voidmain(String[] args) {3 int [] arr = new int[]{4,2,1,6,3,6,0,-5,1,1};4 quickSort(arr,0,arr.length-1);5 //遍历打印排序后的数组

6 for(int i = 0; i < arr.length;i++){7 System.out.print(arr[i]+" ");8 }9 }10 /**

11 *快速排序12 *@exception: array为待排序序列,low为要排序序列的下界,high为要排序序列的上界13 * @date: 2018/8/16 9:4114 */

15 public static void quickSort(int[] array,int low,inthigh){16 if(array==null||array.length==0){17 System.out.println("array is null");18 }19 //划分后的基准元素

20 intstandard;21 //区间长度小于1不需要再进行排序

22 if(low>=high){23 return;24 }25 //对low……high进行划分

26 standard =partition(array,low,high);27 //对左区间进行递归排序

28 quickSort(array,low,standard-1);29 //对右区间进行递归排序

30 quickSort(array,standard+1,high);31 }32 /**

33 *对区间进行划分34 * @date: 2018/8/16 9:4935 */

36 private static int partition(int[] array, int low, inthigh) {37 //进行临界判断

38 if(array==null||array.length==0){39 return 0;40 }41 //基准元素,以区间第一个元素为准

42 int standardValue =array[low];43 //区间长度小于1不需要进行划分

44 if(low>=high){45 returnlow;46 }47 //区间两端交替向中间扫描,直至low=high为止

48 while(low

50 while((low

52 high--;53 }54 //表示找到小于基准元素standardValue值的记录

55 if(low

57 array[low++] =array[high];58 }59 //(standardValue相当于在位置high上)

60 while((low

62 low++;63 }64 //表示找到大于基准元素standardValue值的记录

65 if(low

67 array[high--] =array[low];68 }69 }70 //基准位置被最后定位

71 array[low] =standardValue;72 returnlow;73 }74 }

View Code

归并排序

(1)算法描述

归并算法是在归并操作上的一种有效的排序算法,同样采用分治法。是将已经有序

的子序列进行合并,得到完全的有序序列,即先使得子序列有序,再使子序列段有

序,将两个有序序列合并为一个有序序列,称为“二路合并”。

(2)算法实现

a.将长度为n的序列划分为长度为n/2的两个子序列。

b.分别对这两个子序列采用归并排序。

c.将这两个已经有序的子序列进行合并。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 public classSort {2 public static voidmain(String[] args) {3 int [] arr = new int[]{4,2,1,6,3,6,0,-5,1,1};4 quickSort(arr,0,arr.length-1);5 mergeSort(arr);6 //遍历打印排序后的数组

7 for(int i = 0; i < arr.length;i++){8 System.out.print(arr[i]+" ");9 }10 }11 /**

12 *归并排序13 * array为待排序序列,left、right为序列的左右边界,temp为和原序列长度相等的临时序列14 * @date: 2018/8/16 11:3115 */

16 public static void mergeSort(int[] array){17 //在排序前创建与原数组大小相等的临时数组,避免递归过程中频繁开辟空间

18 int[] temp = new int[array.length];19 mergeSort(array,0,array.length-1,temp);20 }21 private static void mergeSort(int[] array,int left,int right,int[] temp){22 if(left

25 mergeSort(array,left,mid,temp);26 //有半边序列进行归并排序,使得其有序

27 mergeSort(array,mid+1,right,temp);28 //将两个子序列进行合并

29 merge(array,left,mid,right,temp);30 }31 }32 private static void merge(int[] array,int left,int middle,int right,int[] temp){33 if(array==null||array.length==0){34 System.out.println("array is null");35 }36 //左序列指针指向

37 int leftPoint =left;38 //有序列指针指向

39 int rightPoint = middle+1;40 //临时数组的指针指向

41 int tempPoint = 0;42 while (leftPoint<=middle&&rightPoint<=right){43 if(array[leftPoint]<=array[rightPoint]){44 temp[tempPoint++] = array[leftPoint++];45 }else{46 temp[tempPoint++] = array[rightPoint++];47 }48 }49 //将左半序列中的元素添加至temp数组中

50 while (leftPoint<=middle){51 temp[tempPoint++] = array[leftPoint++];52 }53 //将右半序列中的元素添加至temp数组中

54 while(rightPoint<=right){55 temp[tempPoint++] = array[rightPoint++];56 }57 tempPoint = 0;58 //将temp中元素拷贝至原数组中

59 while (left<=right){60 array[left++] = temp[tempPoint++];61 }62 }63 }

View Code

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值