Fork me on GitHub
返回顶部
跳到底部

几种排序算法

快速排序

快速排序是一种基于分治的算法,其基本思想是将一个大数组按照一个【基准数】分为左右两份,左边的部分都不大于基准数,右边的部分都不小于基准数。然后,对这两份在分别应用快速排序,直到剩下一个元素为止。快速排序的平均时间复杂度为nlog(n)。

下面是选取数组最左边的元素为基准元素的快排算法:

//应该随机选择一个数为主元,这里选择最右边的一个数为主元
## 快速排序
int partition(int a[],int left,int right){
	int temp=a[left];//选择数组最左边的元素为基准
	while(left<right){
		while(left<right&&a[right]>temp) right--;
		a[left]=a[right];
		while(left<right&&a[left]<=temp) left++;
		a[right]=a[left];
	}
	a[left]=temp;
	return left;
} 
//法二
int partition(int a[],int left,int right){ 
	int small=left-1;//记录比主元小的数 
	for(int i=left;i<right;i++){
		if(a[i]<a[right]){
			++small;
			if(small!=i){
				swap(a[i],a[small]);
			}
		}
	}
	small++;
	swap(a[small],a[right]);
	
	return small;
}

void quickSort(int a[],int left,int right){
	if(left<right){
		int pos=partion(a,left,right);
		quickSort(a,left,pos-1);
		quickSort(a,pos+1,right);
	}
}

快速排序算法当序列中元素的排列比较随机时效率最高,但是当序列中元素接近有序时,会达到最坏的时间复杂度O(n2),产生这种情况的主要原因在于没有把当前区间划分为两个长度接近的子区间。
解决办法就是随机选取基准元素,也就是对A[left,...,right]来说,不总是用A[left]作为基准元素,而是从A[left],A[left+1].....,A[right]中随机选择一个作为基准元素。
这样对于任意输入数据的期望时间复杂度就能达到O(nlogn)。
另外快速排序是不稳定的。

基于快排的partion函数,还有一道比较常见的面试题就是【求最小/大的k个数】,下面是求最小的k个数。

int partion(vector<int> &input,int left,int right){
    int temp=input[left];
    while(left<right){
        while(left<right&&input[right]>temp){
            right--;
        }
        input[left]=input[right];
        while(left<right&&input[left]<=temp){
            left++;
        }
        input[right]=input[left];
    }
    input[left]=temp;
    return left;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
    int start=0;
    int end=input.size()-1;
    int index=partion(input,start,end);
//        printf("hello %d\n",index);
    while(index!=k-1){
        if(index>k-1){
            end=index-1;
            index=partion(input,start,end);
        }else{
            start=index+1;
            index=partion(input,start,end);
        }
    }
    
    vector<int> rnt;
    for(int i=0;i<k;i++){
    	printf("%d ",input[i]);
    	rnt.push_back(input[i]);
	}
	return rnt;
}

堆排序

堆排序是使用堆这种数据结构来实现的,首先用一个数组实现堆,主要的步骤是向下调整的过程,如下:

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn=10010;
int heap[maxn]={-1,9,8,1,2,6,7,4,3,5,0},n=10;

void downAdjust(int low,int high){
	int i=low,j=i*2;
	while(j<=high){
		if(j+1<=high&&heap[j+1]>heap[j]){
			j++;
		}
		if(heap[j]>heap[i]){
			swap(heap[j],heap[i]);
			i=j;
			j=i*2;
		}else{
			break;
		}
	}
	
}
void createHeap(){
	for(int i=n/2;i>=1;i--){
		downAdjust(i,n);
	}
}
void heapSort(){
	createHeap();
	for(int i=n;i>1;i--){
		swap(heap[i],heap[1]);
		downAdjust(1,i-1);
	}
} 
int main(){
	heapSort();
	for(int i=1;i<=n;i++){
		printf("%d ",heap[i]);
	} 
	
	return 0;
	
}

归并排序

void merge(int a[],int L1,int R1,int L2,int R2){
	int i=L1,j=L2;
	int temp[maxn],index=0;
	while(i<=R1&&j<=R2){
		if(a[i]<a[j]){
			temp[index++]=a[i++];
		}else{
			temp[index++]=a[j++];
		}
	}
	while(i<=R1) temp[index++]=a[i++];
	while(j<=R2) temp[index++]=a[j++];
	for(i=0;i<index;i++){
		a[L1+1]=temp[i];
	}
}
// 递归实现 
void mergeSort(int a[],int left,int right){
	if(left<right){
		int mid=(left+right)/2;
		mergeSort(a,left,mid);
		mergeSort(a,mid+1,rigt);
		mergeSort(a,left,mid,mid+1,right);
	}
}

// 非递归实现
void mergeSort(int a[]){
	for(int step=2;step/2<n;stem*=2){
		for(int i0;i<n;i+=step){
			int mid=i+step/2-1
			if(mid+1<n){
				merge(a,i,mid,mid+1,min(i+stemp-1,n-1));
			}
		}
	}
} 
posted @ 2018-12-30 14:07  sqmax  阅读(229)  评论(0编辑  收藏  举报