//三数取中
int GetMin(int* a, int left, int right)
{
int min = ((right - left) >> 1)+ left;
if (a[min] < a[left])
{
if (a[min] > a[right])
{
return min;
}
else if (a[right]<a[left])
{
return right;
}
else
{
return left;
}
}
else
{
if (a[min] < a[right])
{
return min;
}
else if (a[right] > a[left])
{
return right;
}
else
{
return left;
}
}
}
1、Hoare法:
cpp复制代码
void QuickSort1(int* a, int left, int right)
{
//递归结束条件
/*if (right <= left)
{
return;
}*/
//优化后:递归结束条件变成了当剩下10个以内的元素需要排序时,就使用插入排序
if (right - left + 1 < 10)
{
InsertSort(a + left, right - left + 1);
}
else
{
//3个取中
int mid = GetMin(a, left, right);
//将中的元素换到left
Swp(&a[mid], &a[left]);
int keyi = left;
int begin = left;
int end = right;
while (begin < end)
{
//右边找小的,左边找大的
while (a[end] >= a[keyi] && end > begin)
{
end--;
}
while (a[begin] <= a[keyi] && end > begin)
{
begin++;
}
//交换
Swp(&a[begin], &a[end]);
}
Swp(&a[keyi], &a[begin]);
QuickSort1(a, left, begin - 1);
QuickSort1(a, end + 1, right);
}
}
2、挖坑法:
cpp复制代码
//挖坑法(有一个人要蹲坑)效率差不多
void QuickSort2(int* a, int left, int right){
if (right - left + 1 < 10)
{
InsertSort(a + left, right - left + 1);
}
else
{
int mid = GetMin(a, left, right);
Swp(&a[left], &a[mid]);
int keyi = a[left];
int begin = left;
int end = right;
while (begin < end)
{
//仍然是左边找大,右边找小
while (begin < end && a[end] >= keyi)
{
end--;
}
a[begin] = a[end];
while (begin < end && a[begin] <= keyi)
{
begin++;
}
a[end] = a[begin];
}
a[end] = keyi;
QuickSort2(a, left, begin - 1);
QuickSort2(a, end + 1, right);
}
}
3、前后指针法:
cpp复制代码
//前后指针法:
void QuickSort3(int* a, int left, int right)
{
/*if (left >= right)
{
return;
}*/
if (right - left + 1 < 10)
{
//小于10个数据进行插入排序
InsertSort(a + left, right - left + 1);
}
else
{
int mid = GetMin(a, left, right);
Swp(&a[mid], &a[left]);
int keyi = left;
int prev = left;
int cur = left + 1;
//cur先走,找小的
while (cur <= right)
{
//若小于a[keyi]则prev后移一位 再交换
if (a[cur] <= a[keyi])
{
prev++;
Swp(&a[prev], &a[cur]);
}
cur++;
}
Swp(&a[prev], &a[keyi]);
QuickSort3(a, left, prev - 1);
QuickSort3(a, prev + 1, right);
}
}
4、非递归:
cpp复制代码
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
typedef int LTDataType;
//顺序表(栈)
typedef struct SL
{
LTDataType* a;
int top;
int capacity;
}SL;
//入栈
void SLPush(SL* p,LTDataType x)
{
//不能传NULL,判空;
assert(p);
if (p->top == p->capacity)
{
//先判断是否为0,好进行扩容
int newnode = p->capacity == 0 ? 4 : 2 * (p->capacity);
//扩容;创建一个临时变量接收新的空间,成功在将其交给p->a;
LTDataType* s = (LTDataType*)realloc(p->a,newnode * sizeof(LTDataType));
if (s == NULL)
{
perror("realloc");
return;
}
p->a = s;
p->capacity = newnode;
}
p->a[p->top] = x;
//指向下一个数据地址
p->top++;
}
//出栈(类似尾删)
void SLPop(SL* p)
{
//是否为空
assert(p);
assert(p->top > 0);
p->top--;
}
//初始化
void SLInit(SL* p)
{
p->a = NULL;
p->capacity = 0;
//p->top = -1;//指向栈顶的数据
p->top = 0;//指向栈顶的下一个数据
}
//销毁
void SLDestroy(SL* p)
{
assert(p);
free(p->a);
p->a = NULL;
p->capacity = p->top = 0;
}
//判空
bool SLEmpty(SL* p)
{
//不能是空地址
assert(p);
//为0就是真(true),为1就是假(flase)
return p->top == 0;
}
//数据个数
int SLsize(SL* p)
{
int size = p->top;
return size;
}
//取数据:
LTDataType SLPot(SL*p)
{
assert(p);
return p->a[p->top-1];
}
//非递归,将递归变成迭代,最重要的是区间
void QuickSortNonR(int* a, int left, int right)
{
SL pts;
SLInit(&pts);
SLPush(&pts,right);
SLPush(&pts, left);
while (!SLEmpty(&pts))
{
int begin = SLPot(&pts);
SLPop(&pts);
int end = SLPot(&pts);
SLPop(&pts);
int mid = GetMin(a, begin,end);
Swp(&a[mid], &a[begin]);
int keyi = begin;
int prev = begin;
int cur = begin + 1;
//cur先走,找小的
while (cur <= end)
{
//若小于a[keyi]则prev后移一位 再交换
if (a[cur] <= a[keyi])
{
prev++;
Swp(&a[prev], &a[cur]);
}
cur++;
}
Swp(&a[prev], &a[keyi]);
if (prev + 1 < end)
{
SLPush(&pts, end);
SLPush(&pts, prev + 1);
}
if (prev - 1 > begin)
{
SLPush(&pts, prev-1);
SLPush(&pts, 0);
}
}
SLDestroy(&pts);
}