快速排序-递归和非递归的实现

快速排序主要就是partition的操作。

排序主体

/* 递归的实现。A[] -->要排序的数组, s  --> 开始位置, e  --> 结束位置 */
void quickSort(int arr[], int s, int e)
{
    if (s < e)
    {
        int p = partition(arr, s, e); /* Partitioning index */
        quickSort(arr, s, p - 1);
        quickSort(arr, p + 1, e);
    }
}

划分

//普通划分操作。以最后一个元素 arr[e]作为基准
int partition(int arr[], int s, int e){
    int i = s-1;
    for(int j = s; j<e; j++){
        if(arr[j] <= arr[e]){
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[e], arr[i+1]);
    return i+1;
}

将序列划分为三部分:小于基准元素(i指向最后一个小于基准的元素)、大于基准元素((i,j))和未知元素部分(j指向第一个未知元素)。

划分-随机版本

//随机化的划分操作。已最后一个元素 arr[e]作为基准
int partitionRandom(int arr[], int s, int e){
    //取得一个随机的下标
    int randomIndex = rand() % (e-s+1) + s;
    swap(arr[e], arr[randomIndex]);
    int i = s-1;
    for(int j = s; j<e; j++){
        if(arr[j] <= arr[e]){
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[e], arr[i+1]);
    return i+1;
}

划分–另一种实现

//划分操作的 第二种实现
int partition2(int * arr, int start, int end) {
    int i = start;//指向开头
    int j = end + 1;//指向结尾
    int pivot = arr[start];
    while(true){
       while( i<end && arr[++i] < pivot);//从前到后  第一个比 基准(x)大的数。 j指向该数
       while(j>start && arr[--j] > pivot);//从后向前找到第一个比 基准(x)小的数。i指向该数
        if(i >= j)
            break;
        swap(arr[i], arr[j]);
    }
    arr[start] = arr[j];
    arr[j] = pivot;
    return j;
}

非递归实现

//快速排序的非递归实现
void quicksortIterative(int arr[],int s, int e){
    stack<int> sta;
    sta.push(s);
    sta.push(e);
    while(!sta.empty()){
        int end = sta.top(); sta.pop();
        int start = sta.top(); sta.pop();
        int mid = partitionRandom(arr, start, end);
        //只有元素个数大于1的时候,才放入栈中
        if(mid-1 > start){
            sta.push(start);
            sta.push(mid-1);
        }
        if(end > mid+1){
            sta.push(mid-1);
            sta.push(end);
        }
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-14 21:03:14

快速排序-递归和非递归的实现的相关文章

笔试算法题(55):快速排序实现之非递归实现,最小k值选择(non-recursive version, Minimal Kth Selection of Quick Sort)

议题:快速排序实现之五(非递归实现,短序列优先处理,减少递归栈大小) 分析: 算法原理:此算法实现适用于系统栈空间不足够快速排序递归调用的需求,从而使用非递归实现快速排序算法:使用显示下推栈存储快速排序中的每一次划分结果 (将left和right都压入堆栈),并且首先处理划分序列较短的子序列(也就是在得到一次划分的左右部分时,首先将长序列入栈,然后让段序列入栈), 这样可以保证当快速排序退化的线性效率的时候,栈大小仍旧在㏒N范围内.算法策略类似于最小子树优先遍历规则: 弱势:当序列已经就绪,每次

快速排序 归并排序的非递归版本 备忘

首先,归并排序,分治,递归解决小的范围,再合并两个有序的小范围数组,便得到整个有序的数组. 这是很适合用递归来写的,至于非递归,便是从小到大,各个击破,从而使得整个数组有序.代码如下: void merge(vector<int> &A, int left, int mid, int right) { int i=left,j=mid+1; vector<int> tmp(right-left+1,0); int k=0; while(i<=mid&&

每天刷个算法题20160525:快速排序的递归转非递归解法

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524798 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西

递归与非递归及其相互转换

一.什么是递归 递归是指某个函数直接或间接的调用自身.问题的求解过程就是划分成许多相同性质的子问题的求解,而小问题的求解过程可以很容易的求出,这些子问题的解就构成里原问题的解了. 二.递归的几个特点 1.递归式,就是如何将原问题划分成子问题. 2.递归出口,递归终止的条件,即最小子问题的求解,可以允许多个出口. 3.界函数,问题规模变化的函数,它保证递归的规模向出口条件靠拢 三.递归的运做机制 很明显,很多问题本身固有的性质就决定此类问题是递归定义,所以递归程序很直接算法程序结构清晰.思路明了.

如何将递归转换为非递归

递归函数具有很好的可读性和可维护性,但是大部分情况下程序效率不如非递归函数,所以在程序设计中一般喜欢先用递归解决问题,在保证方法正确的前提下再转换为非递归函数以提高效率. 函数调用时,需要在栈中分配新的帧,将返回地址,调用参数和局部变量入栈.所以递归调用越深,占用的栈空间越多.如果层数过深,肯定会导致栈溢出,这也是消除递归的必要性之一.递归函数又可以分为尾递归和非尾递归函数,前者往往具有很好的优化效率,下面我们分别加以讨论. 尾递归函数 尾递归函数是指函数的最后一个动作是调用函数本身的递归函数,

算法之归并排序的递归与非递归的实现

一.什么是归并排序 归并排序就是将多个有序的数据段合成一个有序的数据段,如果参与合并的只有两个有序的数据段,则称为二路归并.与快速排序和堆排序相比,其最大的特点是一种稳定的算法,算法的平均时间复杂度O(nlog2n). 二.归并排序的基本思路 (1).对于一个原始的待排序表,可以将R[1]到R[n]可以看做是n个长度为1的有序表,即分解. (2).进行第一趟归并,即将上述的n个子序两两合并,得到 n/2向上取整 个有序表,若n为奇数,则归并到最后一个子序列长度为1,即合并. (3).再将两个 n

数据结构——二叉树遍历之“递归与非递归遍历”

简述 二叉树的遍历分为先序遍历.中序遍历和后序遍历.如下图所示: 递归遍历 private void bianli1(List<Integer> list, TreeNode root) { // 先序遍历 if (root == null) { return; } list.add(root.val); bianli1(list, root.left); bianli1(list, root.right); } private void bianli2(List<Integer>

JAVA递归、非递归遍历二叉树(转)

原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private BinTree lchild; private BinTree rchild; public BinTree(char c) { date = c; } // 先序遍历递归 public static void preOrder(BinTree t) {

Java数据结构系列之——树(4):二叉树的中序遍历的递归与非递归实现

package tree.binarytree; import java.util.Stack; /** * 二叉树的中序遍历:递归与非递归实现 * * @author wl * */ public class BiTreeInOrder { // 中序遍历的递归实现 public static void biTreeInOrderByRecursion(BiTreeNode root) { if (root == null) { return; } biTreeInOrderByRecursi

二叉树遍历递归与非递归实现

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 二叉树遍历是二叉树中非常基础的部分,也是学习二叉树必须熟练掌握的部分,下面我们先给出二叉树三种遍历方式的定义,并通过举例来说明二叉树遍历的过程. 二叉树的遍历分为:前序遍历(也叫先序遍历).中序遍历.后序遍历.所谓前.中.后都是根据当前子树根结点相对左右孩子的位置而言,也就是说: 前序遍历:根结点在前,即:根 ----->左------->右: 中序遍历:根结点在中间,即:左------>根------>右: 后序遍历:根结点在最