常见的面试考的排序都在这

一、冒泡排序
每次从头开始依次比较相邻的两个元素,如果后面一个元素比前一个要大,说明顺序不对,则将它们交换,本次循环完毕之后再次从头开始扫描,直到某次扫描中没有元素交换,说明每个元素都不比它后面的元素大,至此排序完成,是一种稳定的排序

最好时间复杂度:O(n)
平均时间复杂度:O(n 2 ^2 2)
最坏时间复杂度:O(n 2 ^2 2​)

void bubble(int a[],int n){
	for(int i=n-1;i>0;i--){
		for(int j=0;j<i;j++){
			if(a[j]>a[j+1]){
				swap(a[j],a[j+1]);
			}
		}
	}
}
二、直接插入排序
假如有n个数,第一趟排序就是比较前两个数将它们排好(默认从小到大),然后在来一个数比较他们三个再排好(即插入到前面的排序),是一种稳定的排序

最好时间复杂度:O(n)
平均时间复杂度:O(n 2 ^2 2)
最坏时间复杂度:O(n 2 ^2 2)

void insert(int a[],int n){
	for(int i=1;i<n;i++){
        for(int j=i;j>0;j--){
            if(a[j]<a[j-1]){
                swap(a[j-1],a[j]);
            }
        }
    }
}
三、选择排序
选择排序每一趟排序会确定一个最小值,不稳定

最好时间复杂度:O(n 2 ^2 2)
平均时间复杂度:O(n 2 ^2 2)
最坏时间复杂度:O(n 2 ^2 2)

void select(int a[],int n){
	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			 if(a[i]>a[j]){
                swap(a[i],a[j]);
            }
		}
	}
}
四、快速排序
快速排序是一种对冒泡排序的改进,第一趟排序以中间的一个数为基准,将数组中比他小的数放在此数的左边,比他大的数放在此数的右边,第二趟排序以第一趟排好的左右的中间一个数为基准,在分别重复上面操作,不稳定

最好时间复杂度:O(n l o g n logn logn)
平均时间复杂度:O(n l o g n logn logn)
最坏平均复杂度:O(n 2 ^2 2)

void quick(int a[],int left,int right){
	if(left>=right){
		return ;
	}
	int i=left;
	int j=right;
	int key=a[i];
	while(i<j){
		while(i<j && a[j]>=key){
			j--;
		}
		a[i]=a[j];	
		while(i<j && a[i]<=key){
			i++;
		}
		a[j]=a[i];
	}
	a[i]=key;
	quicksort(a,left,i-1);
	quicksort(a,i+1,right);
}
五、归并排序
归并算法的核心思想就是分解在合并,也就是分治,分解可以采用递归,设一个数组最右边的元素索引为low,最左边的元素的索引为height,中间元素索引为(low+height)/2,每一次分解可以发现当low==height的时候,整个数组被分解成每一个元素,合并就是将两个有序归并段归并为一个有序的归并段,直到有序为止,是一种稳定的排序

最好时间复杂度:O(n l o g n logn logn)
平均时间复杂度:O(n l o g n logn logn)
最坏平均复杂度:O(n l o g n logn logn​)

int merge(int left, int mid, int right)
{
    int i = left;
    int j = mid + 1;
    int k = left;
    while(i <= mid && j <= right)
    {
        if(arr[i] <= arr[j])
        {
            temp[k++] = arr[i++];
        }
        else
        {
            temp[k++] = arr[j++];
        }
    }
    while(i <= mid)
    {
        temp[k++] = arr[i++];
    }
    while(j <= right)
    {
        temp[k++] = arr[j++];
    }
    for(int i = left; i <= right; i++)
    {
        arr[i] = temp[i];
    }
    return 0;
}
int merge_sort(int left, int right)
{
    int mid;
    if(left < right)
    {
        mid = (left + right) / 2;
        merge_sort(left, mid);
        merge_sort(mid + 1, right);
        merge(left, mid, right);
    }
    return 0;
}

六、希尔排序
希尔排序相当于对插入排序进行优化,是一种缩小增量排序

希尔排序第一趟按照n/2进行分组,每组分别进行直接插入排序,第二趟按照n/2/2进行分组,每组分别进行直接插入排序,直到增量减至为一,整个文件恰好被分为一组,不稳定

void shell(int arr[], int n){
	int i, j, k;
	int cur, gap;
	for (gap = n / 2; gap > 0; gap /= 2){//步长的选取
        for (i = 0; i < gap; i++){
			//接下来就是插入排序
            for (j = i + gap; j < n; j += gap){//每次加上步长
                if (arr[j] < arr[j - gap]){
                    cur = arr[j];
                    k = j - gap;
                    while (k >= 0 && arr[k] > cur){//记录后移,查找插入位置
                        arr[k + gap] = arr[k];
                        k -= gap;
                    }
                    arr[k + gap] = cur;//找到位置插入
                }
        	}
        }
    }
}
七、堆排序
首先将无需数组构造成一个大根堆(新插入的数据与其父结点比较),固定一个最大值,将剩余的数重新构造成一个大根堆,重复这样的过程。(升序建大堆,降序建小堆),不稳定

最好时间复杂度:O(n l o g n logn logn​)
平均时间复杂度:O(n l o g n logn logn​)
最坏平均复杂度:O(n l o g n logn logn​)

父节点:(i-1)/2
左孩子:2*i+1
右孩子:2*i+2

void Heapify(int arr[],int n,int k)//最大堆调整
{
	if(k<n)
	{
		int max=k;//根结点
		int s1=2*k+1;//左子节点
		int s2=2*k+2;//右子结点
		//找出最大结点
		if(arr[s1]>arr[max]&&s1<n)
			max=s1;
		if(arr[s2]>arr[max]&&s2<n)
			max=s2;
		//交换最大子节点到根结点并做递归
		if(max!=k)
		{
			swap(arr[max],arr[k]);
			Heapify(arr,n,max);
		}
	}
}
void CreateHeap(int arr[],int n)//创建最大堆
{
	int last=n-1;				//最后一个子结点位置
	int parent=(last-1)/2;		//最后一个子结点的父结点
	for(int i=parent;i>=0;i--)	
	{
		Heapify(arr,n,i);		//从最后一个父结点开始做最大堆调整
	}
}
void HeapSort(int arr[],int n)//堆排序
{

	CreateHeap(arr,n);		//创建最大堆
	for(int i=n-1;i>=1;i--)	//依次将最大堆的根结点(最大值)取出
	{
		//将最大堆的根(最大值)换到最后
		swap(arr[i],arr[0]);			
		//除去最大值,对交换后的二叉树做最大堆调整,使二叉树根结点始终为最大值	
		Heapify(arr,i,0);		
	}
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Esaka7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值