快速排序

快速排序的思路

快速排序是一种非常高效的排序算法,采用分治法(Divide and Conquer)策略来把一个序列分为较小和较大的两个子序列。其基本思想如下:

  1. 选择基准

    • 从数列中挑出一个元素,称为“基准”(pivot)。

  2. 分区过程

    • 重新排列数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准后面(相同的数可以放到任一边)。在这个分割结束之后,该基准就处于数列的中间位置。这个称为分割操作。

  3. 递归排序子序列

    • 递归地将小于基准值的子序列和大于基准值的子序列分别进行快速排序。

    • 递归终止条件是子序列为空或只有一个元素。

  4. 合并结果

    • 由于在分割的过程中,子序列已经被放置在了正确的相对位置上,因此不需要额外的合并步骤。

快速排序的步骤示例:

假设有一个数组 [3, 6, 8, 10, 1, 2, 1]

  1. 选择基准值,比如选取第一个元素 3 作为基准。

  2. 分区后得到 [1, 2, 1, 3, 8, 10, 6],此时基准 3 已经位于最终排序后的正确位置。

  3. [1, 2, 1][8, 10, 6] 重复上述步骤。

冒泡排序

冒泡排序是怎么实现的

冒泡排序是一种简单的排序算法,它重复地遍历待排序的列表,比较每对相邻的元素,并交换那些顺序错误的元素。遍历列表的工作是重复进行的,直到没有更多的交换需要发生,这意味着列表已经排序完成。

下面是冒泡排序的基本实现步骤:

  1. 初始化

    • 定义一个整型数组 arr[] 包含需要排序的元素。

    • 计算数组的长度 n

  2. 外层循环

    • 用一个外层循环控制需要进行多少轮比较,通常是 n-1 次,因为每次遍历都会将一个元素放到正确的位置上。

  3. 内层循环

    • 内层循环用于比较和交换元素,每次比较相邻的两个元素。

    • 如果前一个元素大于后一个元素,则交换它们的位置。

    • 内层循环的范围逐渐减小,因为每轮遍历结束后,最大的元素都会被移到数组的末尾。

  4. 排序完成

    • 当外层循环结束时,数组就已经按照升序排列好了。

递归过多会导致什么结果

递归调用过多可能会导致以下几种问题:

  1. 栈溢出

    • 每次函数调用都会在内存栈上分配一定的空间来保存局部变量、参数等信息。

    • 如果递归调用层次过深,会导致栈空间耗尽,从而引发栈溢出错误(Stack Overflow)。

    • 栈溢出错误通常表现为程序崩溃或抛出异常。

  2. 性能问题

    • 每次递归调用都有一定的开销,包括参数传递、返回地址的存储等。

    • 过多的递归调用会增加这些开销,可能导致程序运行缓慢。

    • 对于某些递归问题,如斐波那契数列计算,重复计算相同子问题会进一步降低效率。

  3. 资源消耗

    • 除了栈空间之外,递归还可能占用较多的CPU资源,尤其是在递归调用频繁的情况下。

    • 如果递归层次太深,可能会导致程序响应变慢或系统资源紧张。