快速排序(用递归和栈实现)

简介: 快速排序(用递归和栈实现)


目录

递归实现

用栈的思想实现


递归实现

 

思路如下:

1.选择一个值作为基准值key(一般选最左边或最右边,在这里选最左边)。

2.定义L,R(分别为待排序序列最左边与最右边元素的下标),L从左往右走,R从右往左走(若选最左边为key,R先走;选最右边为key,L先走)。

3.R从右往左走遇到比key小的停下来,接着L从左往右走,遇到比key大的停下来。然后交换R,L对应数组中的值。

4.重复上一步操作,直至L,R二者相遇。将相遇点对应的值与key对应的值交换,此时相遇点左边的值均小于相遇点所对应的值,右边的值均大于相遇点所对应的值。

5.相遇点将待排序序列分为两个子序列,用递归的方式重复上述操作。

6.当左右序列只有一个元素的时候排序完成。

void Swap(int* x, int* y)
{
  int tmp;
  tmp = *x;
  *x = *y;
  *y = tmp;
}
//arr为待排序数组,start为待排序数组第一个元素的下标,end最后一个元素的下标
void QuickSort(int* arr,int start,int end)
{
  int L = start;//Left
  int R = end;//Right
  int key = L;//选择最左边元素为key
  if (L >= R)//序列不存在或者只有一个元素
    return;
  while (L<R)
  {
    //R先走,找小
    while (L<R&&arr[R]>=arr[key])
    {
      R--;
    }
    //L先走,找大
    while (L < R && arr[L] <= arr[key])
    {
      L++;
    }
    Swap(&arr[L], &arr[R]);//L,R都停下来了,交换
  }
  //退出循环,L,R已经相遇
  Swap(&arr[key],&arr[L]);//交换相遇处与key处的值
  //此时key左边的值均小于key处的值,右边的值均大于key处的值
  QuickSort(arr,start,L-1);
  QuickSort(arr,R + 1, end);
}

用栈的思想实现

不使用递归进行快速排序,需要将单趟排序进行分装

int PartSort(int* arr, int start, int end)
{
  int L = start;//Left
  int R = end;//Right
  int key = L;//选择最左边元素为key
  if (L >= R)//序列不存在或者只有一个元素
    return L;
  while (L < R)
  {
    //R先走,找小
    while (L < R && arr[R] >= arr[key])
    {
      R--;
    }
    //L先走,找大
    while (L < R && arr[L] <= arr[key])
    {
      L++;
    }
    Swap(&arr[L], &arr[R]);//L,R都停下来了,交换
  }
  //退出循环,L,R已经相遇
  Swap(&arr[key], &arr[L]);//交换相遇处与key处的值
  //此时key左边的值均小于key处的值,右边的值均大于key处的值
  return L;//新的key——L,R相遇的位置
}

思路如下:

1.先将待排序序列最左边与最右边元素的下标入栈。

2.在栈不为空的情况下进入循环,读取栈中数据记作L,R。

3.将L,R传入部分排序函数,并返回一个将原序列分为左右两部分的下标,记作k。

4.判断左序列是否需要排序,若需要的话将左序列的L,R入栈。右序列进行一样操作。

5.反复执行上述操作,直至栈为空。

void QuickSort(int *arr,int start,int end)
{
  struct Stack ps;//建立栈
  StackInit(&ps);//栈的初始化
  StackPush(&ps, start);
  StackPush(&ps, end);
  while (!StackEmpty(&ps))//栈不为空时进入循环
  {
    int R = StackTop(&ps);//读取R
    StackPop(&ps);//栈顶出栈
    int L = StackTop(&ps);//读取L
    StackPop(&ps);//栈顶出栈
    int key = PartSort(arr,L,R);
    if (L < key-1)//左序列还要进行排序
    {
      StackPush(&ps, L);//左序列L入栈
      StackPush(&ps, key-1);//左序列R入栈
    }
    if(R > key+1)//右序列还要进行排序
    {
      StackPush(&ps, key + 1);//右序列L入栈
      StackPush(&ps, R);//右序列R入栈
    }
  }
}
相关文章
|
1月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
24 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
3月前
|
算法 搜索推荐
快速排序-数据结构与算法
快速排序(Quick Sort)是一种基于分治法的高效排序算法。其核心思想是通过选择基准(pivot),将数组划分为左右两部分,使得左侧元素均小于基准,右侧元素均大于基准,然后递归地对左右两部分进行排序。时间复杂度平均为 O(n log n),最坏情况下为 O(n²)(如数组已有序)。空间复杂度为 O(1),属于原地排序,但稳定性不佳。 实现步骤包括编写 `partition` 核心逻辑、递归调用的 `quickSort` 和辅助函数 `swap`。优化方法有随机化基准和三数取中法,以减少最坏情况的发生。
195 13
|
6月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
301 77
|
5月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
81 11
|
5月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
6月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
222 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
6月前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
115 9
|
6月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
164 7
|
6月前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
162 7