之前关于排序之类的东西总是看过就忘,这次索性来个小总结,亲自动手写一遍代码,眼过千遍不如手过一遍。这次就先写三种简单的排序:冒泡排序,插入排序和选择排序,均选择由小到大排序。
一:冒泡排序(Bubble Sort)
在冒泡排序中,最重要的思想是:两两比较,将两者较少的升上去。每次升到 i 位置的都是带排序数组中最小的数。
这样理解:(从小到大排序)存在10个不同大小的气泡,由底至上地把较少的气泡逐步地向上升,这样经过遍历一次后,最小的气泡就会被上升到顶(下标为0),然后再从底至上地这样升,循环直至十个气泡大小有序。
内循环是未排序数组。
冒泡排序最坏情况的时间复杂度是O(n²)
设数组为nums[0…n-1]。
初始时,i = 0,j = nums.length – 1
两两比较nums[ j – 1 ] 和 nums[ j ],若前者大于后者,后者上移,否则相对位置不动
每次未排序数组都会走一遍。i++并重复第二步直到i==n-1。排序完成。
测试代码如下
public static void bubbleSort(int[] nums){
int i,j;
for(i = 0; i < nums.length; i++){
for(j = nums.length - 1; j > i; j--){
if(nums[j] < nums[j - 1]){
int temp = nums[j];
nums[j] = nums[j - 1];
nums[j -1] = temp;
}
}
}
}
注:若 j 从后往前则是将最小的冒泡到最前合适,若是从前往后则是将最大的冒泡到最后合适。
二:插入排序(Insertion Sort)
直接插入排序的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
其内循环是已排序数组。
设数组为a[0…n-1]。
初始时,a[0]自成1个有序区,无序区为a[1..n-1]。令i=1
将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间。
合并方式为先保存待排序数,比较a[j] 位置与其大小,若大于temp则后移,直至 j < 0或者不大于,把带排序数插入即可。i++并重复第二步直到i==n-1。排序完成。
测试代码如下
public static void insertSort(int[] nums){
int i,j;
for(i = 1; i < nums.length; i++){
int temp = nums[i];
for(j = i - 1 ; j >= 0 && nums[j] > temp; j--){
nums[j + 1] = nums[j];
}
nums[j + 1] = temp;
}
}
三.选择排序(Selection Sort)
冒泡排序的思想为:每一次排序过程,通过相邻元素的交换,将当前没有排好序中的最小移到数组的最左端。而选择排序的思想也很直观:每一次排序过程,我们获取当前没有排好序中的最小的元素和数组最左端的元素交换,循环这个过程即可实现对整个数组排序。冒泡排序在发现比它小的时候就交换,而选择排序是只有在确定了最小的数据之后,才会发生交换。
public static void selectionSort(int[] nums){
int i,j,min;
for(i = 0; i < nums.length ; i++){
for(j = i + 1; j < nums.length; j++){
min = i;
if(nums[min] > nums[j]){
min = j;
}
if(min != i){
int temp = nums[min];
nums[min] = nums[i];
nums[i] = temp;
}
}
}
}