一、直接插入排序(Straight Insertion Sort)
基本操作是,将一个记录插入到一个已经排好序的有序表中,从而得到一个新的、记录数增加1的有序表。一般情况下直接在原数组上进行操作即可。
public void insertSort(int[] nums) {
for(int i = 1;i < nums.length;i++) {
int val = nums[i];
//1、找到nums[i]要插入的位置
int j = i-1;
while(j >= 0 && nums[j] > val)
j--;
if(j == i-1)//说明不用移动元素
continue;
//2、移动元素
for(int t = i-1;t > j;t--)
nums[t+1] = nums[t];
//3、插入元素
nums[j+1] = val;
}
}
算法分析:插入排序的基本操作为比较和移动元素,时间复杂度为,并且为稳定排序,在排序的过程中不会改变原本就有序的元素的相对位置。
二、冒泡排序
冒泡排序就是,将第一元素与第二个元素进行比较,若为逆序则交换,然后继续比较第二个与第三个,依次类推。每躺排序都会将一个最值放到其相应的位置。例如,从升序时,每趟排序,均会将最大值放到后面去
public void bubbleSort(int[] nums) {
for(int i = 0;i < nums.length -1 ;i++) {
for(int j = 0;j < nums.length -1 - i;j++) {
if(nums[j] < nums[j+1]) {
int temp = nums[j+1];
nums[j+1] = nums[j];
nums[j] = temp;
}
}
}
}
算法分析:冒泡排序需要进行比较和交换,时间复杂度为,且是稳定排序
三、快速排序(Quick Sort)
通过一趟排序将待排记录分割成独立的两个部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对这两部分记录继续进行排序。具体操作为:设置两个指针low和high,设置枢轴关键字为pivotkey,则首先从high所指位置起向前搜索找到第一个关键字小于pivotkey的记录和pivotkey互相交换,然后从low所指位置起向后搜索,找到第一个关键字大于pivokey的记录与pivokey互相交换,重复这两个步骤,直到low=high,就完成了一趟排序,pivoykey就在其排序后的位置。再分别对左边和右边进行快速排序
public void quickSort(int[] nums,int low,int high) {
if(low == high || low > high)
return;//说明仅有一个值
int temp1 = low;
int temp2 = high;
int pivotkey = nums[low];
//进行一趟排序
while(low < high) {
while(low < high && nums[high] >= pivotkey) {//从high开始找比pivotkey小的数
high--;
}
nums[low] = nums[high];//找到后与pivotkey交换
while(low < high && nums[low] <= pivotkey) {//从low开始找比pivotkey小的数
low++;
}
nums[high] = nums[low];
}
nums[low] = pivotkey;
//退出循环时候low=high
quickSort(nums,temp1,low-1);//左边的
quickSort(nums,low+1,temp2);//右边的
}
算法分析:快排主要是比较,时间复杂度为,且是不稳定的排序。
四、选择排序(selection Sort)
选择排序的基本思想:每一躺在n-i-1个记录中选取关键字最小的记录作为有序序列的第i个记录
public void selectSort(int[] nums) {
for(int i = 0;i < nums.length-1;i++) {
int min = nums[i];
int index = i;
for(int j = i+1;j < nums.length;j++) {
if(nums[j] < min) {
min = nums[j];
index = j;
}
}
nums[index] = nums[i];
nums[i] = min;
}
}
算法分析:主要是比较,时间复杂度为,是不稳定的排序
五、归并排序(Merging Sort)
归并就是将两个或者两个以上的有序表组合成一个新的有序表。
//归并排序
public void mergeSort(int nums[]) {
if(nums.length < 2)
return;
int mid = nums.length / 2;
int[] left = new int[mid];
int[] right = new int[nums.length - mid];
for(int i = 0; i < mid;i++)
left[i] = nums[i];
for(int i = mid;i < nums.length;i++)
right[i-mid] = nums[i];
//对分解的数组 进一步分解
mergeSort(left);
mergeSort(right);
//当不能再分解时合并
merge(left,right,nums);
}
//将两个数组合并
private void merge(int[] array1,int[] array2,int[] arrayNew) {
//int[] arrayNew = new int[array1.length + array2.length];
int i = 0;
int j = 0;
int k = 0;
while(i < array1.length && j < array2.length) {
if(array1[i] <= array2[j]) {
arrayNew[k] = array1[i];
i++;
}else {
arrayNew[k] = array2[j];
j++;
}
k++;
}
//一定有一组数已经结束
for(;i < array1.length;i++) {
arrayNew[k] = array1[i];
k++;
}
for(;j < array2.length;j++) {
arrayNew[k] = array2[j];
k++;
}
}
算法分析:时间复杂度为,是稳定排序
六、堆排序
七、基数排序
八、上述排序性能比较表
排序方法 | 平均时间复杂度 | 最坏时间复杂度 | 稳定性 |
插入排序 | |||
冒泡排序 | |||
快速排序 | |||
选择排序 | |||
归并排序 | |||
堆排序 | |||
基数排序 |
未完待续。。。。