各种排序算法,时间复杂度On及比较#2

 各种排序算法,时间复杂度On及比较#1

5.QuickSort快速排序

int GetKey(int *a,int left,int right){//取到中间值
    int mid=(left+right)/2;
    if (a[right] > a[left]) {
        if (a[mid] > a[right])return right;
        else if (a[mid] < a[left])return left;
        else return mid;
    }
    else {
        if (a[mid] > a[left])return left;
        else if (a[mid] < a[right])return right;
        else return mid;
    }
}
void QuickSort(int* s,int left,int right,int n){
    if(left>=right)return ;
    int begin=left,end=right;
    int mid= GetKey(s,left,right);
    Swap(&s[mid], &s[begin]);//将取得的mid与begin位交换
    int pivot=begin;
    int key=s[begin];//把开始位置作为坑空出,并用key保存中间值
    while(begin<end){
        while (end > begin) {
            if (s[end] < key) {
                s[pivot] = s[end];
                pivot = end;
                break;
            }
            end--;
        }
        while (begin < end) {
            if (s[begin] > key) {
                s[pivot] = s[begin];
                pivot = begin;
                break;
            }
            begin++;
        }
    }
    s[pivot]=key;
    QuickSort(s,left,pivot-1,n);
    QuickSort(s,pivot+1,right,n);
}

[1]原理

        GetKey得到的是该数组首尾及中间三个数的中间值(防止起始位过小或过大提高排序效率)。之后初始设置pivot为首位(begin),每次大循环分别从尾首判断与比较数key的大小关系,并将符合条件的数放到坑中同时该位置变为坑,循环结束后将key放入最后的坑中。每次操作将对应的key放在操作的那段数组的”中间“(key左边都小于key,可以右边都大于key)。如此递归后最终完成排序。

        以下以{3,1 ,5,2,4}为例:

 

 之后同理,最终得到{1,2,3,4,5}

[2]时间复杂度

与归并排序类似,都是分治算法!

T\left ( n \right )=O\left ( nlogn \right )

[3]拓展方法*

其他方法将中间数放在数组中间。

(1)左右指针

int swapsort(int * a, int n, int left, int right) {//左右指针法(交换)
	int begin = left, end = right;
	int mid = GetKey(a, n, left, right);
	swap(&a[mid], &a[begin]);//将取得的mid与begin位交换让key取到a[mid]
	int i = 0;
	int keyi = begin;//以左边为key为例
	while (begin < end) {
		//找小
		while (begin < end && a[end] >= a[keyi]) {
			end--;
		}
		//找大
		while (begin < end && a[begin] <= a[keyi]) {
			begin++;
		}
		Swap(&a[begin], &a[end]);
	}
	Swap(&a[begin], &a[keyi]);
	return begin;//end
}

(2).前后指针

int front_laterSort(int* a, int n, int left, int right) {//前后指针法
	int mid = Getkey(a, n, left, right);
	Swap(&a[mid], &a[left]);//将取得的mid与begin位交换让key取到a[mid]
	int i = 0;
	int keyi = left;//以左边为key为例
	int cur = left + 1, prev = left;
	while (cur <= right) {
		if (a[cur] < a[keyi]) {
			++prev;
			swap(&a[prev], &a[cur]);
		}
		cur++;
	}
	Swap(&a[prev], &a[keyi]);
	return prev;
}

6.堆排序

void adjust(int * a, int n, int root) {//向下调整算法(从根节点开始,前提是左右子树为大堆(小堆)),以大堆算法为例
    int parent = root;
    int child = parent * 2 + 1;//下标从零开始,默认为左孩子
    while (child<n) {//到“叶节点”就终止
        if (child+1<n&&a[child + 1] > a[child]) {//选出较大的孩子节点赋给child,可能有右孩子不存在的情况
            child++;
        }
        if (a[child] > a[parent]) {//较大的如果比父节点还大则交换两者
            Swap(&a[child], &a[parent]);
            parent = child;
            child = parent * 2 + 1;//更新parent和child
        }
        else break;//没找到,结束
    }

}
void HeapSort(int * a,int n) {//堆排序(本质为选择排序),升序用大堆
    //把数组建成(大)堆
    int i = 0;
    for (i = (n - 1 - 1) / 2; i >= 0; i--) {//从最底端开始依次向上构建大堆,时间复杂度为O(n)
        adjust(a, n, i);
    }
    int last = n - 1;
    while (last >= 0) {//将大堆的首元素和尾元素交换
        Swap(&a[0], &a[last]);
        adjust(a, last, 0);//再把最大的取出来
        last--;
    }

}

[1]原理

        最后排序类似于选择排序,但堆排序的处理更有效率,将数组看作一棵二叉树,通过下标访问各个节点。

        主要原理如下图:

[2]时间复杂度

T\left ( n \right )=O\left ( nlogn \right )

7.各种排序算法时间复杂度比较:

       书接上回, 依旧是10^5的数量级。。。(快排真的很快)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值