快速排序
递归算法:
①随机化法
②三位取中法
③单向划分法
④带头节点的单链表快排
1.算法:定义一个基准(第一个数据arr[low]),从后往前找比基准小的数字,找到往前挪;从前往后找比基准大的数字,找到往后挪,重复上述操作,直到low==high,然后arr[low]=tmp; returnlow;
3.时间复杂度最好情况为O(nlogn),完全有序为O(n^2),空间复杂度O(logn)(因为要递归logn次),稳定性不好(有跨越式交换)
快速排序的一次划分(Partition)的时间复杂度为O(n),空间复杂度为O(1)
快速排序(Quick)的时间复杂为O(logn),空间复杂度为O(logn),需要递归logn次
4.快速排序最大的缺点:越有序越慢,完全有序为O(n^2)
5.快速排序的一次划分(Partition) Quick(int *arr,int low,int high)产生的原因就是因为QuickSort(int *arr,int len)的参数少,通过Quick进行中间转换
6.快速排序是对冒泡(起泡)排序的一种改进,他的思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字(左边)均比另一部分记录的关键字(右边)小,则可分别对这两部分记录继续进行排序,以达到整个序列有序
7.内部排序:待排序记录存放在计算机随机存储器中进行的排序过程
外部排序:待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中需要对外存进行访问的排序过程
//快速排序的一次划分,时间复杂度O(n),空间复杂度O(1)
//一次需要遍历所有数据,所以时间复杂度就是O(n)
int Partition(int *arr,int low,int high)
{
int tmp = arr[low];//基准
while(low<high)
{
//从后往前找比基准小的数字,往前移动
while(low < high && arr[high]>tmp)//比基准大,往前走
{
high--;
}
if(low<high)
{
arr[low] =arr[high];
}
//从前往后找比基准大的数字,往后移动
while(low<high && arr[low]<=tmp)
{
low++;
}
if(low<high)
{
arr[high] = arr[low];
}
}
arr[low] = tmp;
return low;
}
//时间复杂度O(logn),空间复杂度O(logn)
void Quick(int *arr,int low,int high)
{
int par = Partition(arr,low,high);
if(par-1>low)//左边数据超过一个
{
Quick(arr,low,par-1);
}
if(par+1<high)//右边数据超过一个
{
Quick(arr,par+1,high);
}
}
//时间复杂度O(nlogn),空间复杂度O(logn),稳定性不好(有跳跃式的交换)
void QuickSort(int *arr,int len)
{
Quick(arr,0,len-1);
}
快速排序测试
int main()
{
int arr[] = {6,5,4,3,2,1};
QuickSort(arr,sizeof(arr)/sizeof(arr[0]));
Show(arr,sizeof(arr)/sizeof(arr[0]));
return 0;
}
递归写法
1.随机化法
算法描述:随机产生一个下标(pos),和下标为left的数据进行交换,以left的值进行划分
void Show(int* arr, int len)
{
for (int i = 0; i < len; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
}
int Partition(int* arr, int low, int high)
{
int tmp = arr[low];
while (low < high)
{
while (low<high && arr[high]>tmp)
{
high--;
}
if (low < high)
{
arr[low] = arr[high];
}
while (low < high && arr[low] <= tmp)
{
low++;
}
if (low < high)
{
arr[high] = arr[low];
}
}
arr[low] = tmp;
return low;
}
int RandPartition(int* arr, int low, int high)
{
srand(time(NULL));
int pos = rand() % (high-low + 1) + low;
std::swap(arr[pos], arr[low]);
return Partition(arr, low, high);
}
void PassQuick(int* arr, int low, int high)
{
if (low < high)
{
int pos = RandPartition(arr, low, high);
PassQuick(arr, low, pos - 1);
PassQuick(arr, pos + 1, high);
}
}
void QuickSort(int* arr, int len)
{
if (arr == NULL || len < 2)
{
return;
}
PassQuick(arr, 0, len - 1);
}
int main()
{
int arr[] = {1,5,9,6,7,3,8,2,4};
QuickSort(arr, sizeof(arr) / sizeof(arr[0]));
Show(arr, sizeof(arr) / sizeof(arr[0]));
}
2.三位取中法
算法:先算得中间位置的值,然后比较下标为left的值,中间位置的值,下标为right的值,用三个数的中间值和下标为letf的值进行交换,就是三位取中法
void Show(int* arr, int len)
{
for (int i = 0; i < len; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
}
int Partition(int* arr, int low, int high)
{
int tmp = arr[low];
while (low < high)
{
while (low<high && arr[high]>tmp)
{
high--;
}
if (low < high)
{
arr[low] = arr[high];
}
while (low < high && arr[low] <= tmp)
{
low++;
}
if (low < high)
{
arr[high] = arr[low];
}
}
arr[low] = tmp;
return low;
}
//三位取中法
int MidParitition(int* br, int left, int right)
{
int mid = (right - left) / 2 + left;
struct IndexNode
{
int key;
int index;
operator int() const { return key; }
};
struct IndexNode KL = { br[left],left };
struct IndexNode KM = { br[mid],mid };
struct IndexNode KR = { br[right],right };
std::priority_queue<IndexNode> hp;
hp.push(KL);
hp.push(KM);
hp.push(KR);
hp.pop();//删除第一个
struct IndexNode pos = hp.top();//取中间的值
std::swap(br[KL.index], br[pos.index]);//中间的值和left进行交换
return Partition(br, left, right);
}
void PassQuick(int* br, int left, int right)
{
if (left < right)
{
int pos = MidParitition(br, left, right);
PassQuick(br, left, pos - 1);
PassQuick(br, pos + 1, right);
}
}
void QuickSort(int* br, int n)
{
if (br == NULL || n < 2) return;
PassQuick(br, 0, n - 1);
}
int main()
{
int arr[] = {1,5,9,6,7,3,8,2,4};
QuickSort(arr, sizeof(arr) / sizeof(arr[0]));
Show(arr, sizeof(arr) / sizeof(arr[0]));
}
3.单向划分法(从左到右)
void Show(int* arr, int len)
{
for (int i = 0; i < len; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
}
//从左向右一次划分
int LeftPartition(int* arr, int left, int right)
{
int i = left;
int j = left - 1;
int tmp = arr[i];
while (i <= right)
{
if (arr[i] <= tmp)
{
j = j + 1;
swap(arr[j], arr[i]);
}
++i;
}
swap(arr[left], arr[j]);
return j;
}
void PassQuick(int* arr, int left, int right)
{
if (left < right)
{
int pos = LeftPartition(arr, left, right);
PassQuick(arr, left, pos - 1);
PassQuick(arr, pos + 1, right);
}
}
void QuickSort(int* arr, int len)
{
if (arr == NULL || len < 2) return;
PassQuick(arr, 0, len - 1);
}
int main()
{
int arr[] = { 56,12,78,9,34,23,100,56,45,67,89 };
int n = sizeof(arr) / sizeof(arr[0]);
QuickSort(arr, n);
Show(arr, n);
return 0;
}
4.如何将上面的快排写成非递归的形式?
void Show(int* arr, int len)
{
for (int i = 0; i < len; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
}
int Partition(int* arr, int low, int high)
{
int tmp = arr[low];
while (low < high)
{
while (low<high && arr[high]>tmp)
{
high--;
}
if (low < high)
{
arr[low] = arr[high];
}
while (low < high && arr[low] <= tmp)
{
low++;
}
if (low < high)
{
arr[high] = arr[low];
}
}
arr[low] = tmp;
return low;
}
void QuickSort(int* br, int len)
{
if (br == NULL || len < 2) return;
queue<int> qu;
qu.push(0);
qu.push(len - 1);
while (!qu.empty())
{
int left = qu.front(); qu.pop();
int right = qu.front(); qu.pop();
int pos = Partition(br, left, right);
if (left < pos - 1)
{
qu.push(left);
qu.push(pos - 1);
}
if (right > pos + 1)
{
qu.push(pos + 1);
qu.push(right);
}
}
}
int main()
{
int arr[] = { 56,12,78,9,34,23,100,56,45,67,89 };
int n = sizeof(arr) / sizeof(arr[0]);
QuickSort(arr, n);
Show(arr, n);
return 0;
}
或者用“对”
void Show(int* arr, int len)
{
for (int i = 0; i < len; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
}
int Partition(int* arr, int low, int high)
{
int tmp = arr[low];
while (low < high)
{
while (low<high && arr[high]>tmp)
{
high--;
}
if (low < high)
{
arr[low] = arr[high];
}
while (low < high && arr[low] <= tmp)
{
low++;
}
if (low < high)
{
arr[high] = arr[low];
}
}
arr[low] = tmp;
return low;
}
void QuickSort(int* br, int n)
{
if (br == NULL || n < 2) return;
typedef std::pair<int, int> Pair;
queue<Pair> qu;
qu.push(Pair(0, n - 1));
while (!qu.empty())
{
Pair pos = qu.front(); qu.pop();
int mid = Partition(br, pos.first, pos.second);
if (pos.first < mid - 1)
{
qu.push(Pair(pos.first, mid - 1));
}
if (mid + 1 < pos.second)
{
qu.push(Pair(mid + 1, pos.second));
}
}
}
int main()
{
int arr[] = { 56,12,78,9,34,23,100,56,45,67,89 };
int n = sizeof(arr) / sizeof(arr[0]);
QuickSort(arr, n);
Show(arr, n);
return 0;
}
本文详细介绍了快速排序算法的三种实现方式:随机化法、三位取中法和非递归形式,包括递归算法原理、时间复杂度分析、空间复杂度以及各种划分策略。通过实例演示了如何应用这些方法进行快速排序,适合理解排序算法优化和非递归编程技巧。
487

被折叠的 条评论
为什么被折叠?



