首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

带尾部递归的C++快速排序

带尾部递归的C++快速排序是一种基于分治思想的排序算法,它通过将待排序数组划分为较小的子数组,并对子数组进行递归排序,最终将所有子数组合并为一个有序数组。

快速排序的基本思想是选择一个基准元素,将数组分为两部分,使得左边的元素都小于等于基准元素,右边的元素都大于等于基准元素。然后对左右两部分分别进行递归排序,最后将左右两部分合并起来。

快速排序的优势在于其平均时间复杂度为O(nlogn),并且具有原地排序的特点,不需要额外的存储空间。它在处理大规模数据时表现出色,并且在实际应用中被广泛使用。

快速排序适用于各种类型的数据,但在处理有序数组或者重复元素较多的情况下,性能可能会下降。

腾讯云提供了云服务器(CVM)产品,可以满足快速排序算法的运行需求。您可以通过以下链接了解更多关于腾讯云云服务器的信息:

https://cloud.tencent.com/product/cvm

以下是一个带尾部递归的C++快速排序的示例代码:

代码语言:cpp
复制
#include <iostream>
using namespace std;

// 交换数组中两个元素的位置
void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

// 将数组划分为两部分,并返回基准元素的下标
int partition(int arr[], int low, int high) {
    int pivot = arr[high];  // 选择最后一个元素作为基准元素
    int i = low - 1;

    for (int j = low; j < high; j++) {
        if (arr[j] <= pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }

    swap(arr[i + 1], arr[high]);
    return i + 1;
}

// 带尾部递归的快速排序函数
void quickSort(int arr[], int low, int high) {
    while (low < high) {
        int pivotIndex = partition(arr, low, high);

        // 对较小的部分进行递归排序
        if (pivotIndex - low < high - pivotIndex) {
            quickSort(arr, low, pivotIndex - 1);
            low = pivotIndex + 1;
        }
        // 对较大的部分进行递归排序
        else {
            quickSort(arr, pivotIndex + 1, high);
            high = pivotIndex - 1;
        }
    }
}

int main() {
    int arr[] = {9, 5, 7, 2, 1, 8, 3};
    int n = sizeof(arr) / sizeof(arr[0]);

    quickSort(arr, 0, n - 1);

    cout << "Sorted array: ";
    for (int i = 0; i < n; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;

    return 0;
}

该示例代码演示了如何使用带尾部递归的快速排序算法对一个整数数组进行排序。在实际应用中,您可以根据具体需求对代码进行适当修改和优化。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

快速排序递归详解

01 — 前言 我们熟知常见排序算法有:冒泡排序、选择排序、归并排序、插入排序快速排序等;每种都有其不同特点以及解法,并且每种排序都可以找到不同算法思路来解答,拿快速排序来讲,有递归和非递归解法...,以下就讲讲递归快速排序解法。...02 — 快速排序概念 快速排序(Quick Sort)是对冒泡排序一种改进。...从快速排序步骤中我们不难发现:快速排序其实使用是分而治之思想,它排序过程是一个递归调用过程。...} 04 — 总结 采用分而治之递归思想是解决快速排序一个比较好方案,递归思想不止是用到排序里面,也可以用于查找里面,比如当需要在大数据量之中查找某个某个值时,也可以运用这种思想,从而达到提升查询效率

42610

快速排序算法思路分析和C++源代码(递归和非递归)

快速排序由于排序效率在同为O(N*logN)几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司笔试面试喜欢考这个。...快速排序是C.R.A.Hoare于1962年提出一种划分交换排序。它采用了一种分治策略,通常称其为分治法(Divide-and-ConquerMethod)。...*********************************** 效率分析:   快速排序时间主要耗费在划分操作上,对长度为k区间进行划分,共需k-1次关键字比较。   ...总关键字比较次数:O(nlgn)   尽管快速排序最坏时间为O(n*n),但就平均性能而言,它是基于关键字比较内部排序算法中速度最快者,快速排序亦因此而得名。...它平均时间复杂度为O(nlgn)。   快排空间复杂度:在通常情况下为O(log2n),需要使用深O(log2n)栈实现递归,如果是最坏情况的话,很显然就要O(n)空间了。

1.5K70
  • 快速排序 数组+递归实现

    快速排序 数组+递归实现 问题描述: 给定N个元素数组arr[N],需要把数组arr中数排成非递减次序并输出. 基本思想: 1....用一个自定义分割方法split()选取用来作分割元素(也称为partition主元),最简单分割方法是选定待排范围第一个数为partition主元,一趟快排完成后,主元e是数组arr中第i个元素...使用两个跟踪变量(forward和backward),递归地对从i到backward采用快速排序方法quickSort(),并递归地对从forward到i采用快速排序方法quickSort(); 3...注: 数组arr=L区间(主元e左边部分)+主元e+U(未排序部分)+R(主元e右边部分),其中区间U是区间L与区间R夹住部分,每次递归都是让U缩小,直到为0,此时快排结束......e左侧元素排序 quickSort(arr, part_pos+1, backward); // 递归地给主元e右侧元素排序 } int split(int arr[], int forward

    64420

    快速排序详解(递归实现与非递归实现)

    一、快速排序基本思想 快速排序是Hoare于1962年提出一种二叉树结构交换排序方法,其基本思想为:任取待排序元素序列中某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值...div); // 递归排[div+1, right) QuickSort(array, div+1, right); } 上述为快速排序递归实现主框架,会发现与二叉树前序遍历规则非常像,先取中间...QuickSort(a, left, keyi-1); QuickSort(a, keyi+1, right); //不断递归左区间和右区间 } 四、快速排序优化实现 4.1快排特殊情况 上面的写法面对绝大多数情况排序已经可以实现时间复杂度接近...快排使用到了递归思想和方法,但是递归如果递归太深的话就会有爆栈风险,所以在这里也介绍一下快速排序递归实现方法。...快速排序整体综合性能和使用场景都是比较好,所以才敢叫快速排序 2. 时间复杂度:O(N*logN) 3. 空间复杂度:O(logN) 4. 稳定性:不稳定

    24610

    递归式实现快速排序

    快速排序基本思想是寻找一个元素作为基准,将其他元素划分为两部分,其中一部分比基准元素小,另一部分比基准元素大,然后如此继续对这两部分操作下去 快速排序最简单实现就是通过简单递归,实现方式之一是使用双指针...,两个指针同时走,左指针找到大,右指针找到小,然后交换这两个元素位置,问题在于枢纽元素和谁交换,让右指针先走,两个指针走到相同位置时候必然是右指针走到左指针地方了,而左指针指向元素是刚刚交换完比枢纽元素小...,而枢纽元素选是第一个,因此它们进行位置交换就是正确 这里给出C版本,C++版本一般是将int *a,换成std::vector&a void QS(int *a, int low, int...腾位置给枢纽元素 a[i] = pivot; // 放置枢纽元素 QS(a, low, i - 1);// 继续排左边 QS(a, j + 1, high);// 继续排右边 } 而递归改非递归最简单改法就是使用栈...,这样基本上算法没有变化,递归本质也是栈功劳,先递归先入栈 void quickSort(std::vector &arr) { std::stack<std::pair<int,

    7210

    递归与分治之快速排序

    分治法就是把一个大问题分解为多个类型相同子问题,最后把这些子问题解合并起来就是问题解。 快速排序(Quicksort)是对冒泡排序一种改进,采用了分治思想。...快排基本思想: 通过一趟排序将要排序数据分割成独立两部分,其中一部分所有数据都比另外一部分所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,当待排序列数据个数为...1时,自然是有序,以此达到整个数据变成有序序列。...具体算法步骤: 对于待排序列,在一趟排序前,从待排序列中随机选取一个数据作为枢轴量, 使所有小于枢轴量数据位于其左面,所有大于枢轴量数据位于其右面, 然后再依次用该方法对其左面、右面的序列进行排序。...当待排序列个数为1时,代表该部分已经完成排序递归可完成整个序列排序

    84160

    快速排序:高效分割与递归排序领域王者算法

    3.2 递归到小子区间时使用插入排序 3.3 快速排序最终代码 四、快速排序总结 快速排序特性总结: 一、快速排序介绍 快速排序是一种基于分治思想高效排序算法,由Tony Hoare于1960...二、快速排序实现 快速排序是一种基于分治思想高效排序算法其核心就是每次找到最中间位置然后再进行递归继续找到最中间位置然后再分割一直分割到只剩一个数时候那么这个数组就是有序了。...每次找到中间值之后利用分治思想,大问题化为小问题 然后递归进行排序递归完成时每个中间值都找到就是排序时候 而要搞定一个排序首先最先解决就是其中单趟排序下面就是各位大佬想出来单趟排序方法: 先把部分单趟排序搞出来后面来实现整体排序就简单多了...快排最坏情况 快速排序虽然很快时间复杂度一眼看上去都是 N*longN 但这只是最好情况: 注:最坏情况复杂度是 N*N,每次 key 选值都是最小 每次进行递归并不是完全二叉树样子...因为如果有很多数据进行排序的话 快排特性是每次到找到中间值然后再递归所以但递归到了10这个区间时候就大致有序了,而插入排序对有序数组排序最快是 O(N) 所以我们选择当区间为 10 时候采用插入排序来进行排序

    18910

    快速排序:非递归优势与性能详解

    前言 快排性能和各个综合性能都是排序梯队里面最顶尖,虽然我们掌握递归方法来快速实现快排,但是递归堆栈消耗太大了为此我们专门还优化了快排。...文章目录 前言 一、为什么要掌握非递归 二、栈区和堆区大小对比 三、非递归实现快排思想 3.1 利用人工栈来实现递归 3.2 实现代码 四、快速排序总结 快速排序特性总结: 一、为什么要掌握非递归...其实是因为在操作系统概念中栈是一快用来快速存储区域 在32位操作系统中栈一般内存只有 10M 而堆内存划分却达到了 2G 三、非递归实现快排思想 非递归其实就是利用迭代思想来替换递归过程...既然是利用人工栈那么我们首先肯定是先来创建一个栈来把第一个区间录入进去: 然后进行循环当栈位空时候说明我们数组就递归完了 3.2 实现代码 代码演示: // 快速排序递归实现 void QuickSortNonR...快速排序特性总结: 快速排序整体综合性能和使用场景都是比较好,所以才敢叫快速排序 时间复杂度:O(N*logN) 空间复杂度:O(logN) 稳定性:不稳定

    18510

    C语言快速排序(非递归)图文详解

    前言:   上一期分析了快速排序三种写法,这三种写法有一个相同点,都是采用递归形式来实现,那么有没有非递归方法实现呢?...答案是当然有,用非递归方法实现快速排序,其实可以借助数据结构中栈来模拟实现递归过程。...(注意下面的数字代表下标) 好,接下来开始用栈模拟递归:(图中栈中数字均表示下标) 1.第一次入栈: 将整个数组入栈,也就是下标为0-8 2.第一次出栈: 每次出栈,对出栈下标区间进行一次部分排序,...然后再将key左区间和右区间分别入栈,也就是0-3和5-8 3.第二次出栈: 根据栈性质后入先出,所以我们让5-8出栈: 跟上面一样,每次出栈对相应区间进行一次部分排序排序完如下图: 因为在对这个区间进行部分排序时...现在就不难感受出,这其实是在模拟递归过程。

    9110

    【C语言数据结构】排序快速排序及多种优化|递归及非递归版本)

    今日更新了快速排序内容 欢迎大家关注点赞收藏⭐️留言 交换排序 快速排序 快排过程图如下: hoare版代码呈现 void QuickSort(int* a, int begin,int...直到left与right相遇,就交换keyi和left对应值。这是单趟,后续过程重复,可以思考二叉树递归过程,快排递归与其相似(见下图)。 下图中,划红线地方是容易出错地方。...快排优化 三数取中法选key 递归到小子区间时,可以考虑使用插入排序 三数取中法 快排对于有序数据,效率不是很高。 如上图,我们前面的快排是固定选key,也就是左边第一幅图,效率很低。...但不同版本,单趟排序结果可能会不同。...先模拟递归左边,像二叉树递归那样,先入右边数,再入左边,这样出时候就先出左边,然后就可以模拟先往左边递归了。

    17510

    图解快速排序C++实现)

    大家好,又见面了,我是你们朋友全栈君。 参考大话数据结构这本书对快速排序讲解,本文作一个梳理,并在最后给出快排C++实现代码。...不论是从小到大排序还是从大到小排序快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式。...因此快速排序最差时间复杂度和冒泡排序是一样都是O(N2),它平均时间复杂度为O(NlogN)。...C++代码实现(从小到大排序) //快速排序(从小到大) void quickSort(int left, int right, vector& arr) { if(left >= right...quickSort(i + 1, right, arr);//递归右边 } 从大到小排序(稍稍改动而已) //快速排序(从大到小) void quickSort(int left, int right

    75930

    【初阶数据结构】打破递归束缚:掌握非递归快速排序与归并排序

    图片个人主页: 是店小二呀C语言笔记专栏: C语言笔记C++笔记专栏: C++笔记初阶数据结构笔记专栏: 初阶数据结构笔记喜欢诗句:无人扶我青云志 我自踏雪至山巅一、非递归实现快速排序void...s, left);} if (keyi + 1 < right){STPush(&s, right);STPush(&s, keyi+1);}}STDestroy(&s);}过程解析:非递归实现快速排序也是需要通过快速排序思想来走...,基本思想是以某数值为基准值,不断将待排序集合分割成两组子序列,采用前序遍历方法根 左子树 右子树,对于递归过程中我们知道左子树会演变为新根,也会分为新根 新左子树 新右子树,然后我们将采用栈来模拟递归过程...说明不存在数据,不需要压栈,等到栈为空结束排序。二、非递归实现归并排序由于快速排序采用是前序遍历满足栈相关数据结构特性,然后归并排序属于后序排序因此不是通过使用栈区模拟非递归实现归并排序。...如果采用栈去模拟实现非递归归并排序,由于归并排序不像快速排序不是出栈既排序,而是等到栈为空,开始归并排序,然而没有归并操作这种做法。

    7910

    C++斐波那契数列(备忘录递归

    C++斐波那契数列(备忘录递归) 斐波那契数列数学形式就是递归,写成代码就是这样: int fib(int N) { if (N == 1 || N == 2) return 1;...假设 n = 20,请画出递归树: [在这里插入图片描述] PS:但凡遇到需要递归问题,最好都画出递归树,这对你分析算法复杂度,寻找算法低效原因都有巨大帮助。 这个递归树怎么理解?...最后遇到 f(1) 或者 f(2) 时候,结果已知,就能直接返回结果,递归树不再向下生长了。 递归算法时间复杂度怎么计算?就是用子问题个数乘以解决一个子问题需要时间。...观察递归树,很明显发现了算法低效原因:存在大量重复计算,比如 f(18) 被计算了两次,而且你可以看到,以 f(18) 为根这个递归树体量巨大,多算一遍,会耗费巨大时间。...这就是动态规划问题第一个性质:重叠子问题。下面,我们想办法解决这个问题。 备忘录递归解法 明确了问题,其实就已经把问题解决了一半。

    1.2K30

    C++快速排序原理深究优化

    下面是归并排序实现,用于和下面的快排进行对比,归并排序是每一次平均分成两部分递归进行排序,然后合并,在任意情况下其时间复杂度都是 O(nlogn),是很稳定排序算法。...二路快排 基于上述经典快排效率退化分析,只要算法能够将基准两边数据分配平均,就能挽回排序效率,所以自然引出了二路快速排序算法,该算法能避免上述因数据过于集中引起灾难。...但仔细考虑其实还有优化空间,因为等于 privot 数据其实已经有序,可以不用加入左右两边进行下面的递归排序。所以自然就引出了三路归并排序算法。...三路快速排序算法原理也非常简单,就是将数据分成三段,分别是小于基数 privot 数据,等于 privot 数据,大于 privot 数据。然后继续递归排序小于和大于 privot 数据。...基于以上原因,三路快排被大部分系统采用,其实 STL 排序核心算法也是采用三路快速排序

    73801

    【数据结构与算法】:非递归实现快速排序、归并排序

    1.非递归实现快速排序 快速排序递归实现主要依赖于栈(stack)来模拟递归过程中函数调用栈。...递归版本快速排序通过递归调用自身来处理子数组,而非递归版本则通过手动管理一个栈来跟踪接下来需要排序子数组边界 那么怎样通过栈来实现排序过程呢?...思路如下: 使用栈实现快速排序是对递归版本模拟。在递归快速排序中,函数调用栈隐式地保存了每次递归调用状态。...,也是一次取一组进行排序递归寻找每个区间 2.归并排序 假如我们已经有了两个已经排序数组,我们如何让他们并为一个有序数组呢?...通常这是通过将数组从中间切分为大致相等两个子数组 递归排序子数组:递归地对这两个子数组进行归并排序,直到每个子数组只包含一个元素或为空,这意味着它自然已经排序好 合并排序子数组:将两个排序子数组合并成一个排序数组

    34010
    领券