• QuickSort


    思想

    分治。选一个pivot,将比pivot小的元素放在左边,比pivot大的元素放在右边,对左右两个子数组递归调用QuickSort。

    实现

    int randomNum(int x, int y) {
    		srand(time(0));  // use system time as seed
    		return x + rand() % (y - x + 1);
    }
    
    int partition(vector<int>& nums, int l, int r) {
    		int pivotIndex = randomNum(l, r);
    		swap(nums[pivotIndex], nums[r]);
    
    		int smaller = l - 1;
    		for (int i = l; i < r; ++i) {
    			if (nums[i] <= nums[r]) {
    				++smaller;
    				swap(nums[smaller], nums[i]);
    			}
    		}
    		++smaller;
    		swap(nums[smaller], nums[r]);
    		return smaller;
    }
    
    void QuickSort(vector<int>& nums, int low, int high) {
    		if(low < high) {
    				int pivotPos = partition(nums, low, high);
    				QuickSort(nums, low, pivotPos - 1);
    				QuickSort(nums, pivotPos + 1, high);
    		}
    }
    
    
    int partition(vector<int>& num, int low, int high) {
    	int pivot = num[low];
    	while (low < high) {
    		while (low < high && num[high] >= pivot) {
    			--high;
    		}
    		num[low] = num[high];
    		while (low < high && num[low] <= pivot) {
    			++low;
    		}
    		num[high] = num[low];
    	}
    	num[low] = pivot;
    	return low;
    }
    
    
    void qSort(vector<int>& num, int low, int high) {
    	if (low < high) {
    		int pivot = partition(num, low, high);
    		qSort(num, low, pivot - 1);
    		qSort(num, pivot + 1, high);
    	}
    }
    
    // 非递归,用栈保存要操作的范围的下标
    void qSortNotR(vector<int>& num, int low, int high) {
    	stack<int> s;
    	s.push(low);
    	s.push(high);
    
    	while (!s.empty()) {
    		int r = s.top();
    		s.pop();
    		int l = s.top();
    		s.pop();
    		int pivotPos = partition(num, l, r);
    		if (l < pivotPos - 1) {
    			s.push(l);
    			s.push(pivotPos - 1);
    		}
    		if (pivotPos + 1 < r) {
    			s.push(pivotPos + 1);
    			s.push(r);
    		}
    	}
    }
    

    性能

    划分的两个子问题规模分别为0和n时,时间复杂度最坏为(O(n^2))
    两个子问题规模相同时,时间复杂度最好为(O(nlgn)),平均性能更接近最好情况。
    假设输入数据的所有排列不是等概率的,那么为了避免最坏情况的发生,选择pivot可以随机进行,这样被pivot分开的两个子问题规模会接近(n/2)

    复杂度的证明既可以用主定理,也可以自己推导,在最优情况下:

    [T(n)=2T(n/2)+n \ T(n)=2(2T(n/4)+n/2)+n=4T(n/4)+2n \ T(n)=4(2T(n/8)+n/4)+2n=8T(n/8)+3n \ ... \ T(n)=nT(1)+nlogn=n+nlogn ]

  • 相关阅读:
    Redis主从同步原理-SYNC【转】
    redis3.0集群部署和测试
    Zabbix3.0配置邮件报警
    3分钟学会git命令的基础使用
    Rsync文件同步工具
    logstash grok 内置正则
    logrotate实现Mysql慢日志分割
    Python之unittest测试代码
    Zabbix如何实现批量监控端口状态
    Centos7搭建Confluence破解版
  • 原文地址:https://www.cnblogs.com/EIMadrigal/p/11524840.html
Copyright © 2020-2023  润新知