经典的排序算法(代码)

经典的排序算法,复习用。

排序方法平均时间复杂度最好情况最坏情况空间复杂度稳定性
冒泡排序O(n*n)O(n)O(n*n)O(1)稳定
选择排序O(n*n)O(n*n)O(n*n)O(1)不稳定
插入排序O(n*n)O(n)O(n*n)O(1)稳定
希尔排序O(n1.5)sss不稳定
堆排序O(nlgn)O(nlgn)O(nlgn)O(1)不稳定
归并排序O(nlgn)O(nlgn)O(nlgn)O(n)稳定
快速排序O(nlgn)O(nlgn)O(n*n)O(n*n)不稳定
计数排序O(n+k)O(n+k)O(n+k)O(k)稳定
桶排序O(n+k)O(n+k)O(n*n)O(n+k)稳定
基数排序O(n*k)O(n*k)O(n*k)O(n+k)稳定

冒泡排序

思想:通过与相邻元素的比较,将较小的元素交换的前面

//冒泡排序O(n^2),稳定算法
//2020年3月23日17:33:40
void BubbleSort(vector<int> nums){
	int i=0,j=0;
	bool flag=true;//标志位,若未发生交换,则表明列表已经有序
	for(;i<nums.size()&&flag;i++){
		flag=false;
		for(j=nums.size()-1;j>i;j--){
			if(nums[j]<nums[j-1])
				swap(nums[j],nums[j-1]);
				flag=true;
		}
	}
}

选择排序

思想:和冒泡排序思想类似,是一次排序后将最小的元素放到最前面
具体做法,就是每次找到最小元素下标,与最前面的元素交换

//选择排序O(n^2)  不稳定算法
//找到最小值的下标
//2020年3月23日21:05:14
void SelectSort(vector<int> &nums){
	int min_a=0;
	for(int i=0;i<nums.size();i++){
		min_a=i;
		for(int j=i+1;j<nums.size();j++){
			if(nums[j]<nums[min_a])
				min_a=j;
		}
		if(i!=min_a)
		swap(nums[i],nums[min_a]);
	}

}

插入排序

思想:维持一个排序数组,每次判断下个元素的插入位置,将插入点后的元素依次后移。

//插入排序O(n^2)系数比前面两种方法小,稳定算法
//2020年3月23日21:15:02
void InsertSort(vector<int> &nums){
	//数组长度小于等于1,没有进行循环操作
	int val=0;
	for(int i=1;i<nums.size();i++){
	//如果nums[i]大于nums[i-1]直接纳入排序数组,不用其他操作
		if(nums[i]<nums[i-1]){
			val=nums[i];//保存该值
			for(int j=i-1;j>=0&&nums[j]>val;j--)
				nums[j+1]=nums[j];
			nums[j+1]=val;
		}
	}

}

希尔排序

思想:将整个记录序列按照增量分割成若干个子序列,某个增量序列进行插入排序。

void Shellsort(vector<int> &nums){
int len=nums.size();
int increment=len;
do{
	increment=increment/3+1;//增量序列
	for(int i=increment;i<len;i++){
		if(nums[i]<nums[i-increment]){
			int tmp=nums[i];
			int j=i-increment;
			for(;j>0&&tmp<nums[j];j-=increment)
				nums[j+increment]=nums[j];
			nums[j+increment]=tmp;
		}
	}
}
while(increment>1);
}

堆排

// 堆排序O(nlgn)
//2020年3月23日21:45:48
void HeapSort(vector<int> &nums){
	//假设数据由1...nums.size()排列
	for(int i=nums.size()/2;i>0;i++){//建立堆
		HeapAdjust(nums,i);
	}
	for(i=nums.size();i>1;i--){//到第二个
		swap(nums[i],nums[1]);
		HeapAdjust(nums,1);
	}

}
// parent(i) i/2
//left(i)  2*i
// right(i) 2*i+1

void HeapAdjust(vector<int>&nums,int i){
	int left=2*i;
	int right=2*i+1;
	int largest=0;
	if(left<=nums.size()&&nums[left]>nums[i])
		largest=left;
	else largest=i;
    if(right<=nums.size()&&nums[right]>nums[largest])
		largest=right;
	if(largest!=i){
		swap(nums[i],nums[largest]);
		HeapAdjust(nums,larget);
	}
}

//build_MAX_heap
void BuildMaxHeap(vector<int>& int nums){
	for(int i=nums.size()/2;i>0;i--)
		HeapAdjust(nums,i);
}

归并排序

思想:采用递归分治的思想,先递归划分子问题,然后合并结果。
时间复杂度O(nlgn),空间复杂度O(n)

//归并排序O(nlgn)
//2020年3月26日16:49:35
//占用内存,效率高且稳定

void Msort(vector<int> &SR,int left,int right){
	if(right-left<=0)//确保区间存在[left,right]
		return;
	int	mid=left+(right-left)/2;
	Msort(SR,left,mid);
	Msort(SR,mid+1,right);//
	Merge(SR,left,mid,mid+1,right);//合并上面两个区间
}

//实现[a,b] [c,d]两个区间的原位合并,外部确定是连续空间
void Merge(vector<int> &SR,int a,int b,int c,int d){

	int i=a;
	int j=c;
	int tmp=0;
	vector<int> St;
	while(i<=b&&j<=d){
		tmp=SR[i]<SR[j]?SR[i++]:SR[j++];
		St.push_back(tmp);
	}
	while(j<=d){
		St.push_back(SR[j++])
	}
	while(i<=b){
	St.push_back(SR[i++])
	}
	for(int m=a;m<St.size();m++){
		SR[m+a]=St[m];
	}
}

快速排序

思想:每次找到一个基数,将区间划分为左右两区间。

//快排 O(nlgn) 2020年3月26日18:30:44 不稳定
//
void  QuickSort(vector<int> & nums){

	Qsort(nums,0,nums.size()-1);
}
void Qsort(vector<int> &nums,int left,int right){
	if (right-left<=0)return;
	int key=Partition(nums,left,high);//找到一个关键值的下标,左边都比他小右边都比他大
	Qsort(nums,left,key-1);
	Qsort(nums,key+1,right);
}
int Partition(vector<int>& nums, int left,int right){
   if(right<left) return -1;//出错
   if(right==left) return left;//不用比较
	int val=nums[left];//选取的比较随意
	//可以用三数取中方法确定,left right mid下标对应的排序后中间的值
	while(left<right){
		while(left<right&&nums[right]>=val){
			right--;
		}
		nums[left]=nums[right];
		//swap(nums[left],nums[right]);
		while(left<right&&nums[left]<=val){
			left++;
		}
		nums[right]=nums[left];
		//swap(nums[left],nums[right]);
	}
	nums[left]=val;
	return  left;

}

void sortsort(int x){
	//稳定排序  O(n*n)   冒泡   插入排序   
	//稳定排序  O(nlgn)  归并排序
	//不稳定排序          快速排序   希尔排序  堆排序  选择排序(选择最小的换)
	
}

计数排序

//外部排序
//计数排序 O(n)
void Countsort(vector<int> &nums ){
	if(nums.empty()) return ;
	int min_val=nums[0],max_val=nums[0];
	for(int i=1;i<nums.size();i++){
		if(min_val>nums[i])
				min_val=nums[i];
		if(max_val<nums[i])
				max_val=nums[i];
		//min_val=min_val>nums[i]?nums[i]:min_val;
		//max_val=max_val<nums[i]?nums[i]:max_val;		
	}
	vector<int> cnt(max_val-min_val+1,0);
	for(int i=0;i<nums.size();i++){
		cnt[nums[i]-min_val]++;
	}
	int k=0;
	for(int i=0;i<cnt.size();i++){
		while(cnt[i]--)
			nums[k++]=min_val+i;
	}
	
}

桶排序

//桶排序 外部排序,桶的数量可以外部定义或者内部定义

void  BucketSort(vector<int> & nums){
	if(nums.empty()) return ;
	int min_val=nums[0],max_val=nums[0];
	for(int i=1;i<nums.size();i++){
		if(min_val>nums[i])
				min_val=nums[i];
		if(max_val<nums[i])
				max_val=nums[i];
		//min_val=min_val>nums[i]?nums[i]:min_val;
		//max_val=max_val<nums[i]?nums[i]:max_val;		
	}
	
	int bucketcnt=nums.size()/2;//桶的数量
	vector<vector<int>> buckets(bucketcnt,vector<int>());
	int bucketsize=ceil(static_cast<double>((max_val-min_val+1)/bucketcnt));
	for(int i=0;i<nums.size();i++){
		int bucketindex=(nums[i]-min_val)/bucketsize;
		buckets[bucketindex].push_back(nums[i]);
	}
	int k=0;
	for(auto bucket: buckets){
		if(!bucket.empty()) {
			SelectSort(bucket);
			for(int value:bucket){
				nums[k++]=value;
			}
		}
	}
	
}

参考书籍:《大话数据结构》、《算法导论》
参考博客:
十大经典排序算法及C++实现
经典排序算法C++实现(10种)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值