排序算法:
- 插入排序:直接插入排序,希尔排序
- 交换排序:冒泡排序,快速排序
- 选择排序:简单选择排序,堆排序
- 归并排序
1. 直接插入排序
(1) 直接插入排序: 依次将待排序序列中的每一个记录插入到一个已经排好序的序列中,直到所有记录都排好序.
(2) 时间复杂度:最好情况下,即待排序序列为正序,时间复杂度为O(n);最坏情况下,即待排序序列为逆序,时间复杂度为O(n^2);平均情况下,时间复杂度为O(n^2).
(3) 空间复杂度: O(1)
(4) 代码如下:
//ascending
public static void InsertSort(int[] nums){
int len = nums.length;
for(int i=1;i<len;i++){
int j;
for(j=i;j>0;j--){
if(nums[j]<nums[j-1]){
int temp = nums[j];
nums[j] = nums[j-1];
nums[j-1] = temp;
}
}
for(j=0;j<len;j++)
System.out.print(nums[j]+" ");
System.out.print("\n");
}
}
2. 希尔排序
(1) 希尔排序是对直接插入排序的改进;
(2) 希尔排序: 先将整个待排序序列分割成若干个子序列, 在子序列内分别进行直接插入排序, 待整个序列中的记录基本有序时, 再对全体记录进行一次直接插入排序;固定增量大小的分为一组;
(3) 时间复杂度: O(nlogn)~O(n^2)
(4) 空间复杂度: O(1)
实现代码如下:
public static void shellSort(int[] nums){
int len = nums.length;
int d = len/2; //增量大小
int k;
while(d>0){
k=0;
while(k<d){
for(int i=k;i<len;i+=d){
for(int j=i;j>=0&&j-d>=0;j-=d){
if(nums[j]<nums[j-d]){
int temp = nums[j];
nums[j] = nums[j-d];
nums[j-d] = temp;
}
}
}
k++;
}
d/=2;
for(int j=0;j<len;j++)
System.out.print(nums[j]+" ");
System.out.print("\n");
}
3. 冒泡排序
(1) 冒泡排序:从头开始,两两比较相邻记录的关键码,如果是反序则交换,直到没有反序的记录为止。
(2) 时间复杂度:在最好情况下,即待排序序列为正序, 其时间复杂度为O(n);在最坏情况下,待排序序列为逆序,时间复杂度为O(n^2),平均时间复杂度为O(n^2).
(3) 空间复杂度:O(1)
(4) 实现代码:每一次外循环将最大的值移到后面,后面是有序的
public static void bubbleSort(int[] nums){
int len = nums.length;
for(int i=len-1;i>=0;i--){
for(int j=0;j<i;j++){
if(nums[j]>nums[j+1]){
int temp = nums[j+1];
nums[j+1] = nums[j];
nums[j] = temp;
}
}
for(int j=0;j<len;j++)
System.out.print(nums[j]+" ");
System.out.print("\n");
}
}
4. 快速排序
(1) 快速排序是对冒泡排序的改进.
(2) 快速排序流程: 首先选一个参考值, 将待排序序列分割成独立的两部分, 左侧的值均小于参考值,右侧的值均大于或等于参考点;接着对这两部分分别重复这一过程,直到整个序列有序.
(3) 时间复杂度: 最好情况下,每次划分参考值的时候左侧子序列与右侧子序列的长度相同,时间复杂度为O(nlogn);最坏情况下,待排序序列为正序或逆序,时间复杂度为O(n^2);平均情况下,时间复杂度为O(nlogn).
(4) 空间复杂度: O(logn)
(5) 算法实现代码如下:
public static void quickSort(int[] nums,int low,int high){
int mid;
if(low<high){
mid = partition(nums,low,high);
quickSort(nums,low,mid-1);
quickSort(nums,mid+1,high);
}else
return;
}
public static int partition(int[] nums,int low,int high){
int temp = nums[low]; //选取做左边的为参考值
while(low<high){
while(high>low&&nums[high]>=temp)
high--;
nums[low] = nums[high];
while(low<high&&nums[low]<temp)
low++;
nums[high] = nums[low];
}
nums[low] = temp;
for(int j=0;j<nums.length;j++)
System.out.print(nums[j]+" ");
System.out.print("\n");
return low;
}
5. 简单选择排序
(1) 简单选择排序: 将最小值的下标和值记录下来,一轮遍历完后,进行一次交换;第i轮时,前i-1个值大小顺序已经排好.
(2) 时间复杂度: 最好最坏平均情况下都是O(n^2)
(3) 空间复杂度: O(1)
(4) 代码如下:
public static void selectSort(int[] nums){
int len = nums.length;
int j;
for(int i=0;i<len-1;i++){
int sIndex=i,sValue=nums[i];
for(j=i+1;j<len;j++){
if(nums[j]<sValue){
sValue = nums[j];
sIndex = j;
}
}
nums[sIndex] = nums[i];
nums[i] = sValue;
for( j=0;j<nums.length;j++)
System.out.print(nums[j]+" ");
System.out.print("\n");
}
}
6. 堆排序
(1) 堆排序是对简单选择排序的改进;
(2) 堆排序: 使用最小堆排序后的是递减数组;
堆的存储:一般都使用数组来表示堆,i节点的父节点下标为(i-1)/2.它的左右子节点下表为2i+1,2i+2;
(3) 时间复杂度: 最好,最坏,平均的时间复杂度都是O(nlogn)
(4) 空间复杂度: O(nlogn)
(5) 实现代码如下:
minHeap(nums,nums.length);
minHeapSort(nums,nums.length);
//从第i个节点开始调整,num为节点总数,i节点的子节点为2i+1,2i+2
public static void minHeapFix(int[] nums,int i,int num){
int j = 2*i+1;
int temp = nums[i];
while(j<num){
//找出左右孩子节点中值最小的节点
if((j+1)<num&&nums[j+1]<nums[j])
j++;
//说明父节点依然是以其为根的节点中的最小点
if(nums[j]>temp)
break;
//将值小的子节点替换其父节点
nums[i] = nums[j];
//由于替换后,父节点的到来可能使得其子树不再是最小堆,故需要继续调整
i=j;
j = 2*i+1;
}
nums[i] = temp;
}
//建立最小堆
public static void minHeap(int[] nums,int len){
//从下往上调整最小堆,忽略叶子节点,因为叶子节点自身就是最小堆
for(int i=len/2-1;i>=0;i--){
minHeapFix(nums,i,len);
}
}
public static void minHeapSort(int[] nums, int len){
minHeap(nums,len);//得先构建最小堆,此时第0个元素即是堆中最小的值,再实现排序
int temp;
for(int i=len-1;i>=1;i--){
temp = nums[0];
nums[0] = nums[i];
nums[i]=temp;
minHeapFix(nums,0,i);
for(int j=0;j<nums.length;j++)
System.out.print(nums[j]+" ");
System.out.print("\n");
}
}
7. 归并排序
(1) 归并排序: 将2个有序序列合并成一个有序序列为止;关键在于合并.
(2) 时间复杂度: 最好,最坏,平均的时间复杂度都是O(nlogn)
(3) 空间复杂度: O(n)
(4) 实现代码如下:
- 申请空间,空间大小为2个有序序列大小之和,用于存放排好序后的元素;
- 2个指针,分别指向2个已排序的序列,进行合并;
<span style="font-size:18px;">public static void mergeSort(int[] nums,int low,int high){
int mid = (low+high)/2;
if(low<high){
mergeSort(nums,low,mid);
mergeSort(nums,mid+1,high);
merge(nums,low,mid,high);
}
else
return;
}
public static void merge(int[] nums,int low,int mid,int high){
int[] temp = new int[high-low+1];
int left = low, right = high,center = mid+1;
int i=0;
while(low<=mid&¢er<=high){
if(nums[low]<nums[center]){
temp[i++] = nums[low];
low++;
}
else{
temp[i++] = nums[center];
center++;
}
}
while(low<=mid){
temp[i++] = nums[low++];
}
while(center<=high){
temp[i++] = nums[center++];
}
for(i=0;i<right-left+1;i++)
nums[left+i] = temp[i];
for(int j=0;j<nums.length;j++)
System.out.print(nums[j]+" ");
System.out.print("\n");
}</span>