快速排序中的区间划分

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。该方法的基本思想是:

1.先从数列中取出一个数作为基准数。

2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

3.再对左右区间重复第二步,直到各区间只有一个数。

算法的思路很清晰,但是如果在区间划分过程中边界值没有处理好,也是很容易出现bug的。下面给出两种比较清晰的思维来指导区间划分代码的编写。

第一种思维即所谓的挖坑法思维,下面通过分析一个实例来分析一下挖坑法的过程:

以一个数组作为示例,取区间第一个数为基准数。

0

1

2

3

4

5

6

7

8

9

72

6

57

88

60

42

83

73

48

85

初始时,left = 0; right= 9;   X = a[left] = 72

由于已经将a[0]中的数保存到X中,可以理解成在数组a[0]上挖了个坑,可以将其它数据填充到这来。

从right开始向前找一个<=X的数。显然,right=8时,符合条件,将a[8]挖出再填到上一个坑a[left]中。 这样一个坑a[0]就被搞定了,但又形成了一个新坑a[8],这怎么办了?简单,再找数字来填a[8]这个坑。这次从left开始向后找一个大于X的数,当left=3,符合条件,将a[3]挖出再填到上一个坑a[right] 中;

数组变为:

0

1

2

3

4

5

6

7

8

9

48

6

57

88

60

42

83

73

88

85

再重复上面的步骤,最终数组将变成如下形式:

0

1

2

3

4

5

6

7

8

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是非递归快速排序的Python实现: ```python def quicksort(arr): # 使用栈来保存需要处理的子数组的左右边界 stack = [(0, len(arr) - 1)] # 只要栈不为空,就继续排序 while stack: left, right = stack.pop() # 如果子数组只有一个元素,那么不需要排序 if left >= right: continue # 将子数组划分为两个部分,并找到分割点的位置 pivot = arr[left] i, j = left, right while i < j: while i < j and arr[j] >= pivot: j -= 1 arr[i] = arr[j] while i < j and arr[i] <= pivot: i += 1 arr[j] = arr[i] arr[i] = pivot # 将左右子数组的边界压入栈,以便进行下一轮排序 stack.append((left, i - 1)) stack.append((i + 1, right)) return arr ``` 该算法使用栈来保存需要处理的子数组的左右边界。每次从栈弹出一个边界,将子数组划分为两个部分,并找到分割点的位置。然后,将左右子数组的边界压入栈,以便进行下一轮排序。在排序结束时,返回已排序的数组。 ### 回答2: 非递归快速排序是一种常见的排序算法,它可以快速地对一个数组进行排序。 首先,我们需要借助一个栈来实现非递归快速排序。将整个数组作为一个区间,初始时将整个区间入栈。 然后,不断地从栈取出一个区间,并对该区间进行划分操作。划分操作将选定的枢轴元素放置在合适的位置上,并将小于枢轴的元素放在枢轴左侧,大于枢轴的元素放在枢轴右侧。 接下来,如果划分后的左右两个区间都非空,将它们分别入栈。如果左区间非空,则将左区间入栈;如果右区间非空,则将右区间入栈。这样就保证了后续处理的区间仍然是乱序的。 重复上述步骤,直到栈为空或只有一个区间时,排序过程结束。 下面是一个示例代码: ```python def quick_sort(arr): stack = [] stack.append((0, len(arr) - 1)) while stack: left, right = stack.pop() if left >= right: continue pivot = arr[left] i, j = left, right while i < j: while i < j and arr[j] >= pivot: j -= 1 while i < j and arr[i] <= pivot: i += 1 arr[i], arr[j] = arr[j], arr[i] arr[left], arr[i] = arr[i], arr[left] if i-1 > left: stack.append((left, i-1)) if i+1 < right: stack.append((i+1, right)) return arr arr = [6, 5, 3, 1, 8, 7, 2, 4] print(quick_sort(arr)) ``` 在这个示例,我们使用了一个栈来模拟递归的过程,实现了非递归的快速排序。最后输出的结果是将数组 `[6, 5, 3, 1, 8, 7, 2, 4]` 进行快速排序后的结果 `[1, 2, 3, 4, 5, 6, 7, 8]`。 ### 回答3: 非递归快速排序是一种常用的排序算法,通过分治的思想将数组分为两部分,一部分小于基准元素,一部分大于基准元素,然后递归地对两部分进行排序。下面是一种非递归快速排序的实现方法。 首先,我们需要选择一个基准元素。一般情况下,可以选择数组的第一个元素作为基准元素。 接下来,我们用两个指针i和j分别指向数组的起始位置和结束位置。我们需要不断地移动指针i和j,同时判断他们所指向的元素是否需要交换位置。 具体的操作如下: 1. 初始化 i=low、j=high,将基准元素保存在一个变量pivot。 2. 从 j 开始向前搜索,直到找到第一个小于或等于 pivot 的元素,将其移动到 i 的位置,同时 i 向后移动一位。 3. 从 i 开始向后搜索,直到找到第一个大于或等于 pivot 的元素,将其移动到 j 的位置,同时 j 向前移动一位。 4. 重复步骤2和3,直到 i 和 j 相遇。 5. 将基准元素移动到 i 的位置。 6. 接下来,如果 i 之前的数组长度大于1,则对 i 之前的数组进行快速排序。 7. 如果 i 之后的数组长度大于1,则对 i 之后的数组进行快速排序。 通过不断进行以上操作,最终整个数组就会被排序。 需要注意的是,在实现快速排序的过程,可以使用一个栈来模拟递归的过程,使其变为非递归实现。 非递归快速排序的时间复杂度为O(nlogn),空间复杂度为O(logn)。它具有快速、高效的特点,是一种常用的排序算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值