排序(二)

  • 冒泡排序
    冒泡排序很简单,将最大的数放在最后,或者将最小的数放在最前面即可。
    最好情况比较次数为n-1,移动次数为0,最好情况下的时间复杂度为O(n)
    最坏情况的时间复杂度为O(n^2 ) 平均时间复杂度为O(n^2)
    代码
void bubble_sort(int num[],int n)
{
	//将最大的数下沉 
	for(int i=0;i<n-1;i++)
	{
		for(int j=0;j<n-i-1;j++)
		{
			if(num[j]>num[j+1])
			{
				int tem=num[j];
				num[j]=num[j+1];
				num[j+1]=tem;
			}
		}
	}
	//将最小的数上浮
	for(int i=0;i<n-1;i++)
	{
		for(int j=n-1;j>i;j--)
		{
			if(num[j]<num[j-1])
			{
				int tem = num[j];
				num[j]=num[j-1];
				num[j-1]=tem;
			}
		}
	} 
} 
  • 快速排序
    快速排序一点要记住,快速排序是基于分治法的,每次选一个标兵,通过一趟的排序将待排序表划分为独立的两部分,是的标兵的坐标全是小于标兵的元素,标兵的右边全是大于标兵的元素。然后再以标兵的左边作为子表重新进行排序,标兵的右边作为子表重新进行排序,直到low=high
    快速排序空间复杂度:快排是递归。需要借助一个递归工作栈来保存每层递归调用的必要信息,其容量应与递归调用的最大深度一致,最好情况下为log2(n+1),最坏情况下进行n-1递归调用,站的深度为O(n),平均情况下栈的深度为O(log2n)
    快排的时间复杂度:与划分是否对称有关,若初始排序表基本有序或者基本逆序时,最坏情况下的时间复杂度为O(n^2)。最理想的情况下,能做到均匀的划分,此时时间复杂度为O(nlog2n)。但快速排序平均情况下的运行时间与其最佳的运行时间很接近,而不是接近最坏情况下的运行时间
    快速排序是一种不稳定的排序
    这里有一个小题:如果是要取第k大的元素也可以利用快排,主要是利用partition函数,当标兵最后确定的位置,也就是low是k的时候,就可以结束并输出了,如果标兵的low小于了k,那么就在标兵的右边,则在quick_sort(num,mid+1,high)中进行继续查找,若标兵的low大于了k,那么就在标兵的左边,quick_sort(num,low,mid-1)中继续查找,直到找到为止
int partition(int num[],int low,int high)
{
	int pkey = num[low];
	while(low<high)
	{
		while(low<high&&pkey<=num[high])
		{
			high--;
		}
		num[low]=num[high];
		while(low<high&&pkey>=num[low])
		{
			low++;
		}
		num[high]=num[low];
	}
	num[low]=pkey;
	//cout<<num[low]<<" "<<low<<endl;
	return low;
}
void quick_sort(int num[],int low,int high)
{
	if(low<high)
	{
		int mid = partition(num,low,high);
		quick_sort(num,low,mid-1);
		quick_sort(num,mid+1,high);
	}
}
  • 简单选择排序
    选择排序就是每次选最大或者最小的放在最后或者最前面
void select_sort(int num[],int n)
{
	for(int i=0;i<n-1;i++)
	{
		int min = i;
		for(int j=i+1;j<n;j++)
		{
			if(num[j]<num[min])
			{
				min = j;
			}
		}
		int tem=num[i];
		num[i]=num[min];
		num[min]=tem;
	}
} 
  • 堆排序
    堆排序我这里只做了大顶堆,并且还不是很懂。都是我太笨了wwww
    堆排序是一种完全二叉树的结构,n个关键字序列,num[i]<=num[i2],num[i]<=num[i2+1]为小顶堆,um[i]>=num[i2],num[i]>=num[i2+1]。
    值得注意的是,堆最好从1开始,从0开始我不是很懂。
    堆排序主要是先构造初始堆(大顶堆),构造初始堆的方法是从k=n/2开始到1,逐步向下调整,每次都找子节点中较大的那个开始筛选,如果比父节点要小,那么筛选结束,这个k没有可以调整的,如果比父节点要大,那么要需要交换父节点和子节点的位置,并将k该变为子节点的编号,继续向下筛选,并调整为大顶堆
    初始堆的第一个元素是整个表中最大的元素,最终堆排序是每次将堆中的第一个元素与最后一个交换位置,然后调整从第一个元素到第n-1个元素调整堆为大顶堆,然后再取第一个元素和最后一个交换位置,这样调整n-1趟结束排序
    空间复杂度 O(1)
    时间复杂度建堆时间为O(n),之后有n-1次向下调整的操作,每次调整的操作时间复杂度为O(h),堆排序的时间复杂度为O(n*log2n)
    堆排序是一种不稳定的排序方法
void adjustDown(int num[],int k,int n)
{
	int tem = num[k];
	for(int i=k*2;i<=n;i*=2)
	{
		if(i<n&&num[i]<num[i+1])
			i++;
		if(tem>=num[i])
			break;
		else
		{
			num[k]=num[i];
			num[i]=tem;
			k=i;
		}
	}
	
}
void build_max_heap(int num[],int n)
{
	for(int i=n/2;i>0;i--)
	{
		adjustDown(num,i,n);
	}
}
void heap_sort(int num[],int n)
{
	build_max_heap(num,n);
	//为什么是大于1,为什么是1 
	for(int i=n;i>1;i--)
	{
		int tem=num[1];
		num[1]=num[i];
		num[i]=tem;
		adjustDown(num,1,i-1);
	}
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值