总结:七种排序
一、冒泡排序(以下皆以从小到大排序为例)
1.时间复杂度
平均情况:O(n^2)
最好情况:O(n)
最坏情况:O(n^2)
2.空间复杂度:O(1)
3.稳定性:稳定(没有发生跳跃式的交换)
4.代码示例
public static int[] bubbleSort(int[] arr) {
if(arr == null || arr.length <= 1){
return arr;
}
for(int i=0;i<arr.length-1;i++){
int a=0;
for(int j=0;j<arr.length-1-i;j++){//每次循环结束后最后一个元素为当前最大元素
if(arr[j]>arr[j+1]){//将大数往后移
int tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
a++;
}
}
if(a==0){//所有数有序
break;
}
}
return arr;
}
二、选择排序(从待排序数字的后面找到比当前待排序数字小的数字进行交换)
1.时间复杂度
平均情况:O(n^2)
最好情况:O(n^2)
最坏情况:O(n^2)
2.空间复杂度:O(1)
3.稳定性:不稳定(发生了跳跃式的交换)
4.代码示例
public static int[] selectionSort(int[] arr) {
for(int i = 0;i < arr.length;i++){
for(int j = i + 1;j < arr.length;j++){
if(arr[j] < arr[i]){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
return arr;
}
三、直接插入排序(越有序越快)
1.时间复杂度
平均情况:O(n^2)
最好情况:O(n)
最坏情况:O(n^2)
2.空间复杂度:O(1)
3.稳定性:稳定
4.代码示例
public static int[] insertionSort(int[] arr){
for(int i = 1;i < arr.length;i++) {
int tmp = arr[i],j=0;
for (j = i - 1; j >= 0; j--) {
if(arr[j] > tmp){//将比i大的往后移
arr[j+1] = arr[j];
}else{
break;
}
}
arr[j+1] = tmp;//将i放回
}
return arr;
}
四、Shell排序(组内进行有序(插入排序))
1.时间复杂度
平均情况:O(n^1.3)
最好情况:O(n)
最坏情况:O(n^2)
2.空间复杂度:O(1)
3.稳定性:不稳定
4.代码示例
public static int[] shellSort(int[] arr,int gap) {
for(int i = gap;i < arr.length;i++) {
int tmp = arr[i], j = 0;
for (j = i - gap; j >= 0; j = j - gap) {
if(arr[j] > tmp){
arr[j + gap] = arr[j];
}else{
break;
}
}
arr[j + gap] = tmp;
}
return arr;
}
五、快速排序
1.时间复杂度
平均情况:O(nlog2n)
最好情况:O(nlog2n)
最坏情况:O(n^2)
2.空间复杂度:O(log2n)
3.稳定性:不稳定
4.代码示例
(1)快速排序的递归算法
public static int partion(int[] array,int low,int high){
int tmp = array[low];
int count = 1;
while(low<high){
if(count%2==1) {//利用count实现前后的轮替交换
if (array[high]< tmp) {//从后面找小的
array[low]=array[high];
count++;
}else {
high--;
}
}else {
if(array[low]>tmp){//从前面找大的
array[high] = array[low];
count++;
}else {
low++;
}
}
}
array[low]=tmp;
return low;
}
public static void quick(int[] array,int low,int high){
int par = partion(array,low,high);
if(par > low+1){
quick(array,low,par-1);
}
if(par<high-1){
quick(array,par+1,high);
}
}
public static void quickSort(int[] array){
quick(array,0,array.length-1);
}
(2)快速排序的非递归算法
public static int partion(int[] array,int low,int high){
int tmp = array[low];
int count = 1;
while(low<high){
if(count%2==1) {
if (array[high]< tmp) {
array[low]=array[high];
count++;
}else {
high--;
}
}else {
if(array[low]>tmp){
array[high] = array[low];
count++;
}else {
low++;
}
}
}
array[low]=tmp;
return low;
}
public static void quickSort1(int[] array){
int len = (int)(log((double)array.length)/log((double)2));
int[] stack = new int[2*len];//用栈存储low和high
int top = 0 ;
int low = 0 ;
int high = array.length-1;
int par = partion(array,low,high);
if(par>low+1){
stack[top] = low;
top++;
stack[top] = par-1;
top++;
}
if(par<high-1){
stack[top] = par+1;
top++;
stack[top] = high;
top++;
}
while(top!=0){
top--;
high=stack[top];
top--;
low = stack[top];
par = partion(array,low,high);
if(par>low+1){
stack[top] = low;
top++;
stack[top] = par-1;
top++;
}
if(par<high-1){
stack[top] = par+1;
top++;
stack[top] = high;
top++;
}
}
}
5.快速排序的优化(以下两种是对基准选取的优化)
(1)随机
public static int selectPivotRandom(int array[],int low,int high){
Random random = new Random();
int pivotPos = random.nextInt(high-low+1)+low;
int tmp = array[low];
array[low]=array[pivotPos];
array[pivotPos]=tmp;
return array[low];
}
(2)取中
public static void midThree(int[] array,int low,int high){
int mid = (high+low)/2;
if(array[low]>array[high]){//实现mid<low<high
int tmp = array[low];
array[low]=array[high];
array[high]=tmp;
}
if(array[mid]>array[low]){
int tmp = array[low];
array[low]=array[mid];
array[mid]=tmp;
}
if(array[mid]>array[high]){
int tmp = array[high];
array[high]=array[mid];
array[mid]=tmp;
}
}
六、归并排序(使每个子序列有序,再使子序列段间有序)
1.时间复杂度
平均情况:O(nlog2n)
最好情况:O(nlog2n)
最坏情况:O(nlog2n)
2.空间复杂度:O(n)
3.稳定性:稳定
4.代码示例
public static void merge(int[] array,int gap){
int[] tmpArr = new int[array.length];
int i = 0;
int s1 = 0;
int e1 = s1+gap-1;
int s2 = e1+1;
int e2 = s2+gap-1 < array.length ? s2+gap-1:array.length-1;
while(s2<array.length){
while(s1<=e1&&s2<=e2){
if(array[s1]<array[s2]){
tmpArr[i]=array[s1];
i++;
s1++;
}
if(array[s2]<array[s1]){
tmpArr[i]=array[s2];
i++;
s2++;
}
}
if(s1>e1){
while(s2<=e2){
tmpArr[i]=array[s2];
i++;
s2++;
}
}
if(s2>e2){
while(s1<=e1){
tmpArr[i]=array[s1];
i++;
s1++;
}
}
s1 = e2+1;
e1 = s1+gap-1;
s2 = e1+1;
e2 = s2+gap-1 < array.length ? s2+gap-1:array.length-1;
}
while(s1<array.length){
tmpArr[i] = array[s1];
i++;
s1++;
}
for(int j = 0 ;j<array.length;j++){
array[j] = tmpArr[j];
}
}
public static void mergeSort(int[] array){
for(int i = 1;i<array.length;i*=2){//循环使每次的子段长度增加
merge(array,i);
}
}
七、堆排(建立大根堆)
1.时间复杂度
平均情况:O(nlog2n)
最好情况:O(nlog2n)
最坏情况:O(nlog2n)
2.空间复杂度:O(1)
3.稳定性:不稳定
4.代码示例
public static void adjust(int[] array,int start,int end){
int tmp = array[start];
for (int i = 2*start+1; i <= end ; i = 2*i+1) {
//判断是否有右孩子,如果有,找到左右孩子的最大值。
if((i < end) && array[i] < array[i+1]) {
i++;
}//肯定i是最大值的下标
if(array[i] > tmp) {
array[start] = array[i];
start = i;
}else {
break;
}
}
array[start] = tmp;
}
public static void heapSort(int[] array){
for(int i = (array.length-1-1)/2;i>=0;i--){//建立大根堆
adjust(array,i,array.length-1);
}
int tmp = 0;
for (int i = array.length-1; i >0 ; i--) {
tmp = array[i];
array[i] = array[0];
array[0]=tmp;
adjust(array,0,i-1);
}
}