简单排序算法(冒泡排序、选择排序、插入排序)
一、冒泡排序
1、介绍:
冒泡排序和选择排序的思想是蛮力法,冒泡,顾名思义,每次选择后面一个元素(最大或者最小)冒上来,从而得到一个有序的序列。比如对于序列:10、8、5、7、3、1的冒泡第一趟演示图示如图所示
可见第一趟过后做大元素10已经沉底,第二趟就对另外的8、5、7、3、1进行上述同样的比较冒泡,会使得最大元素8沉底,...... ,最终可得到一个有序序列。
2、代码实现(Java):
/**
* 冒泡排序
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] bubbleSort(int...args){ //这里使用JDK提供的可变参数作可变数组
for(int i=0;i<args.length-1;i++){
for(int j=args.length-1;j>i;j--){ //这里从右向左扫描
if(args[j]<args[j-1]){
int temp = args[j];
args[j] = args[j-1];
args[j-1] = temp;
}
}
}
return args;
}
程序中有两个for循环,在args[i]左边的元素是已经沉底的,排序好了的元素;j作为一个扫描指针,从右向左扫描,如果j-1位置的大于j位置的元素,则交换它们,直到把最小的那个元素沉底到i+1位置。
3、代码优化
对于上述代码,可以发现对于一个大部分有序的序列来说,上面的做法很多步骤是徒劳的不会产生有效的交换,所以,我们想到可以加一个标志位,来标志一趟扫描过后是否发生交换,如果未发生交换,则说明序列已经有序,无需再继续下去
优化后的代码:
/**
* 冒泡排序的优化算法
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] bubbleSort2(int...args){
boolean flag = true; //是否交换标志位
for(int i=0;i<args.length-1&&flag;i++){
flag = false;
for(int j=args.length-1;j>i;j--){
if(args[j]<args[j-1]){
int temp = args[j];
args[j] = args[j-1];
args[j-1] = temp;
flag = true; //发生交换则让标志位为真
}
}
}
return args;
}
测试一下,对于一个大部分有序的序列,优化后的算法比之前的算法要节省很多步。
测试方法:
public static void main(String[] args) {
TestBubbleSort t = new TestBubbleSort();
//int[] array = t.bubbleSort(1,3,4,7,9,5,23,2);
int[] array = t.bubbleSort2(1,3,4,7,9,5,23,2);
for(int i:array){
System.out.println(i);
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二、选择排序
1、介绍:
选择排序开始的时候,我们扫描整个待排序列表,找到最小的那一个,并与第一位的元素进行交换;接着,扫描第2~n位的共n-1个元素,找到最小的那一个,并与第2位的元素进行交换;以此类推,........;最后,扫描第n-1~n位的共2个元素,找到最小的那一个,并与第n-1位的元素进行交换。至此,扫描结束排序完毕,得到了一个非递减列表。
下面以一个整形数组作为待排序列表,描述上述的选择排序过程:
待排序整形数组:6、4、9、1、4、12
第一次:扫描整个列表,找到最小的元素,也就是1,过程如下
扫描第一个元素6,最小元素6,最小元素索引0
扫描第一个元素4,与最小元素6比较,6不小于4,所以,最小元素4,最小元素索引1
扫描第一个元素9,与最小元素4比较,9不小于4,所以,最小元素4,最小元素索引1
扫描第一个元素1,与最小元素4比较,1小于4, 所以,最小元素1,最小元素索引3
扫描第一个元素4,与最小元素1比较,4不小于1, 所以,最小元素1,最小元素索引3
扫描第一个元素12,与最小元素1比较,12不小于1, 所以,最小元素1,最小元素索引3
扫描结束,最小元素1,最小元素索引3,将1与6交换,得到序列:1、4、9、6、4、12
第二次:扫描第2~6位的元素,也就是4、9、6、4、12
扫描第一个元素4,最小元素4,最小元素索引1
扫描第一个元素9,与最小元素4比较,9不小于4,所以,最小元素4,最小元素索引1
扫描第一个元素6,与最小元素4比较,6不小于4,所以,最小元素4,最小元素索引1
扫描第一个元素4,与最小元素4比较,4不小于4, 所以,最小元素4,最小元素索引1
扫描第一个元素12,与最小元素4比较,12不小于4, 所以,最小元素4,最小元素索引1
扫描结束,最小元素4,最小元素索引1,将4与4交换,得到序列:1、4、9、6、4、12
第三次:以此类推,得到1、4、4、6、9、12
第四次:以此类推,得到1、4、4、6、9、12
第五次:以此类推,得到1、4、4、6、9、12
全部扫描结束,排序完成,得到非递减序列:1、4、4、6、9、12
2、代码实现(Java):
/**
* 选择排序的Java代码实现
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] selectSort(int...args){ //这里使用JDK提供的可变参数作可变数组
for(int i=0;i<args.length-1;i++){
for(int j=i+1;j<args.length;j++){
if(args[i]>args[j]){
int temp = args[i];
args[i] = args [j];
args[j] = temp;
}
}
}
return args;
}
程序中有两个for循环,j=i+1作为扫描指针,若i位置的元素大于j位置的元素,则把两者交换,并使j+1,这样当 j 扫描到末尾结束后,i位置上的元素就是本次扫描中最小的那一个,然后i+1。最终,可得一个非递减的序列。但是我们发现上述代码做了很多次元素的交换,而交换元素又是费时费力的,所以改良后的代码是在扫描的过程中不急于做元素的交换,而是用一个变量记下最小元素的位置,更新一个变量的值比做一次元素交换要容易的做,最后将最小元素与i位置的元素交换,这样整个过程我们至多做一次交换。
3、优化后的选择排序算法的Java代码实现:
/**
* 优化后的选择排序Java代码实现
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] selectSort2(int...args){
int k,num = 0;
for(int i=0;i<args.length-1;i++){
k = i; //设置k变量的目的是为了减少交换的次数,把交换改为对k赋值,每趟循环至多交换1次
for(int j=i;j<args.length;j++){
if(args[k]>args[j]){
k = j;
}
}
if(k != i){
int temp = args[k];
args[k] = args[i];
args[i] = temp;
}
}
return args;
}
测试代码:虽然优化后的代码和之前的代码复杂度一样,但是对于一个大量数据的排序其运行时间比之前的代码要少很多。
public static void main(String[] args) {
TestSelectSort ts = new TestSelectSort();
//TestSelectSort ts = new TestSelectSort2();
int[] array = ts.selectSort(5,3,8,2,15,2,11,0);
for(int i:array){
System.out.println(i);
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
三、插入排序
1、介绍:
对于一个含有n个元素的序列,对它的插入排序的过程是这样的,我们区第一个元素,它一定是有序的(因为只有一个元素),将第二个元素插入到这个有序序列中去(也就是和第一个元素比较,然后插入),再将第3个元素插入到前面;两个元素组成的有序序列中去,.......,最后将第n个元素插入到由前面(n-1)个元素组成的有序序列中去,可以发现这是减治思想的一种体现。
2、插入排序代码实现:
/**
* 插入排序的Java代码实现
*@author DR
* @param args
* @return
*2014年1月14日
*/
public int[] insertSort(int...args){ //这里使用JDK提供的可变参数作可变数组
for(int i=1;i<args.length;i++){
if(args[i-1]>args[i]){
int key = args[i];
int j=i-1;
for(;j>=0 && args[j]>key;j--){
args[j+1] = args[j];
}
args[j+1] = key;
}
}
return args;
}
注意一点:事实上,插入排序一共有三种:①我们可以从左向右扫描序列,找到合适的位置插入; ②我们可以从右向左扫描序列,找到合适的位置插入;③对于有序序列我们可以使用折半查找到合适的位置插入。 这里由于不知道序列是否有序,我们采用第②中插入法,事实上,很多像这种对数组的排序都采用第②中方法,因为它可以在比较查找的过程中移动腾空位置,比第一种要少做一次循环,这一点可以去验证一下。
总结:之所以是简单排序,因为这三种排序的算法相对简单,最好、最坏、平均情况的时间复杂度都是O(n²)。
分享到:
相关推荐
本资源提供了七大经典排序算法的实现程序,包括快速排序、冒泡排序、选择排序、归并排序、插入排序、希尔排序和堆排序。下面将逐一详细介绍这些排序算法及其原理。 1. 快速排序:由C.A.R. Hoare提出,是一种采用...
本话题主要探讨六种内部排序算法:直接插入排序、希尔排序、冒泡排序、快速排序、选择排序以及堆排序。这六种排序算法各有优劣,适用于不同的场景,接下来我们将逐一进行详细阐述。 1. **直接插入排序**: 直接...
总的来说,这段代码提供了四种排序算法的实现,分别是冒泡排序、选择排序、插入排序以及Java内置的数组排序。每种排序算法都有其适用场景,理解这些算法可以帮助我们更好地解决实际问题,并根据需求选择合适的排序...
插入排序是一种简单的排序算法,它的基本思想是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。在C++中,可以使用两层循环实现,外层循环控制未排序部分,内层循环寻找插入...
数据结构(c语言版)严蔚敏 吴伟民编著 中直接插入排序、折半排序、shell排序、冒泡排序、快速排序、选择排序、堆排序的实现、归并排序,使用c语言实现
在本文中,我们将深入探讨四种经典的排序算法:插入排序、选择排序、基数排序和冒泡排序,以及它们在C++语言中的实现。 **插入排序(Insertion Sort)** 插入排序是一种简单直观的排序算法,它的工作原理类似于我们...
本文将深入探讨Java编程语言中实现的七种主要排序算法:直接插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序以及归并排序。每种算法都有其独特性,适用于不同的场景和数据特性。 1. **直接插入排序**:...
1. **冒泡排序**:这是一种简单的排序算法,通过重复遍历待排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。冒泡...
插入排序是最简单的排序算法之一,它的工作原理类似于手动整理扑克牌。遍历数组,将每个元素插入到已排序的部分,保持已排序部分的顺序。对于小规模或部分有序的数据,插入排序效率较高。其平均和最坏情况下的时间...
以上六种排序算法各有优缺点,如选择排序和冒泡排序时间复杂度较高,但实现简单;插入排序在部分有序的情况下效率较高;基数排序适用于处理大量整数排序;快速排序平均性能优秀,但最坏情况下时间复杂度较高;归并...
排序算法汇总(选择排序、直接插入排序、冒泡排序、希尔排序、快速排序、堆排序) 本资源介绍了六种常用的排序算法:选择排序、直接插入排序、冒泡排序、希尔排序、快速排序和堆排序。下面对每种算法进行详细介绍:...
根据给定的文件信息,我们将深入探讨几种经典的排序算法,包括选择排序、冒泡排序、交换排序、希尔排序、插入排序以及基数排序。这些算法在计算机科学领域内有着广泛的应用,各自具有独特的特点和适用场景。 ### 1....
经典C语言排序算法 ...冒泡排序、选择排序和插入法排序都是基本的排序算法,虽然它们的效率不高,但它们的实现简单易懂,易于学习和理解。同时,这些算法也可以作为其他排序算法的基础,例如快速排序和归并排序等。
直接插入排序、冒泡排序和简单选择排序是三种常用的排序算法,它们分别应用于不同的场景中。在本实验报告中,我们将详细介绍这三种排序算法的实现过程。 一、直接插入排序 直接插入排序是一种简单的排序算法,它的...
插入排序是一种简单的排序算法,它的工作原理类似于我们日常生活中整理扑克牌。首先,我们假设数组的第一个元素已经排序好,然后从第二个元素开始,依次将每个元素插入到已排序部分的正确位置。这个过程会不断重复...
本文将详细探讨五种常见的排序算法——归并排序、插入排序、冒泡排序和选择排序,以及它们在C语言环境下的时间性能比较。 1. **归并排序**: 归并排序是一种基于分治策略的排序算法,它将大问题分解为小问题,再将...
本资源包含了几种常见的排序算法,包括堆排序、选择排序、冒泡排序、归并排序和插入排序。这些排序算法各有特点,适用于不同的场景,并且在理解它们的工作原理后,能够帮助初学者更好地掌握编程基础。 1. **堆排序*...
直接插入排序、冒泡排序、快速排序、直接选择排序、堆排序和二路归并排序是计算机科学中经典的排序算法,它们在数据处理和算法学习中占有重要地位。这些排序算法各有特点,适用场景不同,下面将逐一详细介绍,并结合...
本篇文章将详细讨论几种常见的排序算法:选择排序、冒泡排序、插入排序、合并排序以及快速排序,分析它们的算法原理、时间效率,并通过经验分析验证理论分析的准确性。 **1. 选择排序(Selection Sort)** 选择排序...
本实验报告主要考察直接插入排序、冒泡排序、快速排序三种数据排序算法的实现和比较。实验中,我们将使用 C 语言编程环境(VC++)编写程序代码,实现这三种排序算法,并对实验结果进行分析和讨论。 直接插入排序...