记事本记录1——排序的理解及复现

基本排序算法总结

1.快速排序法

快速排序法的主要思想是分治法,其功能是通过迭代递归实现。
时间复杂度 :o(nlogn)
空间复杂度 :0(nlogn)
算法主要思想为:

  1. 首先将列表的初始元素设置为一个target。
  2. 设置两个指针 i 和 j,令指针 j 从后向前查找比target值小的元素,找到后就保持j不动,令i从前向后查找第一个比target大的元素,找到后,交换i和j处的值,然后循环上述操作,j 继续向前查找比target小的数值,i继续向后查找比target大的数值,继续交换直到查询后的结果到 i =j; 此时交换i处的值和target值。
  3. 此时,将整个数组空间用 i 位置分为两部分(begin — i-1) 和 (i+1 — end) 。将这两个部分分别再使用前面的查找算法进行分区递归排序即可。
    实现代码
// 快速排序代码块
void quick_sort(int *arr, int end){
	if(begin > end)
		return 0;
	target  = arr[begin];
	int i = begin;
	int j = end;
	while(i!=j)
{
	while(arr[j] > target && i<j) 
		j--;
	while(arr[i] < target&& i<j)
		i++;
	if(i<j){
		int t = arr[i];
		arr[i] = arr[j];
		arr[j] = t;  }
	}
	arr[i] = target;    //令target值交换到他所在的位置
	quick_sort(arr,begin,i-1);//对左区间进行排序
	quick_sort(arr,i+1,end); //对右区间排序
}

时间复杂度解释:因为快速排序不止一次的访问整个数组,但是每次访问的数组大小又不一样。
空间复杂度解释:快速排序在每次访问数组时会对整个数组的某个空间进行访问。

2.冒泡排序法

冒泡排序法是最基础最经典的排序算法之一,很稳定,就是费时间。
时间复杂度:0(n*n)
空间复杂度: o(1)
算法主要思想为:

  1. 整个数组元素从头开始连续两个数值每两个进行排序比较并且交换顺序,每轮交换会产生整个数组中最大的元素被挑选出来,并被移动到数组的最后。
    2.第二次交换会遍历数组从头开始到倒数第二个数值结束。遍历求出第二大的数值。
// 冒泡排序的实现
void bubble_sort(vector<int> &arr)
{
	int n = arr.size();
	for(int i=0; i<n;i++)//i表示是第几轮查找和排序。
	{
		for(int j=0; j<n-i;j++)
		{
			if(arr[j] > arr[j+1]){
				int t = arr[i];
				arr[i] = arr[j];
				arr[j] = t;
		}
	}
}

3.快速选择排序

可用于求解第k个元素的问题
时间复杂度:0(n*n)
空间复杂度: o(1)
算法主要思想为:(比如在一个长度为N的数组中找到一个第K大的元素)
跟快速排序类似,会在数组中首先选择出来一个target(基准数),并在线性时间内定义其在排序数组中的位置,

  1. 先随意选择出一个target,一般为数组的第一个元素。
    2.使用如快速排序一样的算法将该数字放在合适的位置(pos)上,将小于基准的元素放在左边,将大于基准的元素放在右边。
    3.比较pos 和 N-k的大小区别。如果pos > N-k,则查看Pos左边区域,若pos<N-k,则查看pos右边区域。这就是选择排序。
    例如:使用选择排序求得长度为6的数组中第2大的元素,即求拍好后的序列中地(6-2)=4个元素。
// 冒泡排序的实现
void quick_select_sort(vector<int> &arr, int k)
{
	int n = arr.size();
	int t = n - k ;//求第2大元素就是求第t小的元素,也就是从小到大排序后的第t个元素。
	result = select(arr,0,n-1,t); //创建了寻找从小到大排序后的t位置处的元素。
	return result;
}

int select(vector<int> &arr, int begin, int end,int tar){//选择快速排序
{
	if (begin>end){  return arr[begin];   }
	int f = quick_sort(arr,begin,end);//找到第一次排序后最左边数据的位置,使用快速排序
	if(tar == f) return arr[tar];//若排序后的数据位置等于目标位置,就返回值
	else if(tar > f) return select(arr, f+1,end,tar-f);//若排序后的数据位置小鱼目标位置,就递归排序位置后面的区域空间
	else return select(arr, begin,f-1,tar);
}

int quick_sort(vector<int> &arr, int begin, int end){//快速排序,用于使用第一次排序把最左边的数排序到合适的位置。
	int target = arr[begin];
	int i = begin;
	int j = end;
	while(i!=j)
	{
		while(arr[i] < target && i<j) i++;
		while(arr[j] > target && i<j) j--;
		if(i<j){
			int t = arr[i];
			arr[i] = arr[j];
			arr[j] = t;
	}	
}
arr[i] = target;    //将最终位置上的结果与target进行交换
return i;
}

4.堆排序

堆是求解K个最小或最大元素的方式,可以维护一个大小为K的堆,小顶堆中维护的就是数组中最大的K个元素,大顶堆中维护的是数组中最小的K个元素。
将数组所有元素加入堆中,并且保持堆的大小为k,堆中就保持了k个最大的元素。
小顶堆的堆顶元素就是第K个最大元素。
堆的实现方式

// 创造优先级队列,让优先级高的排列在前面,优先出队,priority_queue<Type,Container,Functional>
//Functional为比较优先级的方式
//作为队列的一个延伸,优先队列包含在头文件<queue>中。
1.//堆的升序队列  即小顶堆
priority_queue<int,vector<int>,greater<int>> q; //堆中为最大的几个元素,堆顶元素为堆中第K大元素。
2.//堆的降序队列,即大顶堆
priority_queue<int,vector<int>,greater<int>> q;//堆中为最小的几个元素,堆顶元素为堆中第k小元素。
var foo = 'bar';

使用堆排序的例子:例如求数组arr的第k大元素。

int findK(vector<int>& arr, int k)
{
	int n = arr.size();
	if(n==0 || n<k){
		return 0;}
	priority_queue<int,vector<int>,greater<int>> store;//创建了一个小顶堆存放前K个最大的元素
	//向小顶堆中添加元素
	for (int i=0; i<n;i++){
		store.push(arr[i]);//向堆中添加元素,堆存在的优先级会使得小顶堆中的元素是排序的。
		if(store.size()>k) store.pop();//若堆中元素大于k时,就删除堆顶元素。
		}
	return store.top();//堆顶元素就是第K大元素。
}

5.桶排序

桶排序是为了解决第K个最大概率的数
桶排序可以通过堆排序实现。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值