快排基本逻辑:
首先我们来用挖坑法实现:首先确定一个“坑”,分左右两部分,确定首与尾值以及“坑”所对应的值,按升序方式则为右部分选择小值与“坑”对应的值比较,左边选大值与“坑”比较。从左或右比较选值根据”坑“的位置在左还是右再比较 左边则从右边选,右边则从左边选。
- 接下来我们就用代码来实现
- 下述代码为避免首项就为最小值问题而增加消耗而加入了Getmid函数获取三项中的中间值
void Quict_sort(int* dat, int left, int right)
{
if (left >= right)
{
return;
}
int index=Getmid(dat, left, right);
Swap(dat[left], dat[index]);
int begin = left;
int end = right;
int pivot = begin;
int core = dat[pivot];
while (begin < end)
{
while (begincore)//小值
{
end--;
}
dat[pivot] = dat[end];
pivot = end;
while (begin < end && dat[begin] < core)//大值
{
begin++;
}
dat[pivot] = dat[begin];
pivot = begin;
}
pivot = begin;
dat[pivot] = core;
Quict_sort(dat, left, pivot - 1);//递归左半部分
Quict_sort(dat, pivot + 1, right);//递归右半部分1
}
三位取中增加效率
int Gitmid(int* dat, int left, int right)
{
assert(dat);
int mid = (left + right) >> 1;
if (dat[left] < dat[mid])
{
if (dat[mid] < dat[right])
{
return mid;
}
else if (dat[left] > dat[right])
{
return left;
}
else
return right;
}
else
{
if (dat[mid] > dat[right])
{
return mid;
}
else if (dat[left] < dat[right])
{
return left;
}
else
return right;
}
}
下述类似于挖坑法,通过前后比较得出key应该放的位置
//左右指针法
void Quict_sort(int* a, int left, int right)
{
if (left >= right)
{
return;
}
int index=Gitmid(a, left, right);
Swap(a[left], a[index]);
int key = left;
int pre = left; int cur = left + 1;
while (cur <= right)
{
if (a[cur] < a[key] && ++pre!=cur)
{
Swap(a[pre], a[cur]);
}
++cur;
}
Swap(a[key], a[pre]);
int pivot = pre;
Quict_sort(a, left, pivot - 1);//递归左半部分
Quict_sort(a, pivot + 1, right);//递归右半部分
}
- 上述该左右指针法也类似与挖坑法,也为比较排序寻找该key在有序数据中的中间位置而通过控制两下标加加选小值交换而达到目的
- 我们已然清楚了快排的具体实现,而非递归则是将递归部分利用栈存储下标,通过出栈入栈而达到递归的效果,思路于上述类似。
归并排序
基本思路:只需假设有序后分治递归,依次比较即可
void MergSort_(int* dat, int left, int right, int* tmp)
{
if (left >= right)
{
return;
}
int mid = (left + right) >> 1;
//假设有序,进行分治递归
MergSort_(dat, left, mid , tmp);
MergSort_(dat, mid + 1, right, tmp);
//定义变量
int begin1 = left; int end1 = mid;
int begin2 = mid + 1; int end2 = right;
int index = left;
while (begin1 <= end1 && begin2 <= end2)
{
if (dat[begin1] < dat[begin2])
{
tmp[index++] = dat[begin1++];
}
else
{
tmp[index++] = dat[begin2++];
}
}
while (begin1 <= end1)//考虑到比较完可能有剩余值直接放入数组即可
{
tmp[index++] = dat[begin1++];
}
while (begin2 <= end2)
{
tmp[index++] = dat[begin2++];
}
for (int i = left; i <= right; i++)
{
dat[i] = tmp[i];
}
}
void MergeSort(int* dat, int num)
{
int* tmp = (int*)malloc(num * sizeof(int));
MergSort(dat, 0, num - 1, tmp);
free(tmp);
}
上述则为归并排序
- 类似于希尔排序,通过定义一个gap,再通过循环每排完一次,两数直接比较的空隙就翻倍,最终最后一组通过首项与末项比较确定有序。
void MergeSort(int* dat, int num)
{
int* tmp = (int*)malloc(num * sizeof(int));
int gap = 1;
while (gap < num)
{
for (int i = 0; i < num; i += 2 * gap)
{
int begin1 = i; int end1 = i + gap - 1;
int begin2 = i + gap; int end2 = i + 2 * gap - 1;
int index = i;
if (begin2 >= num)//防止越界
break;
if (end2 >= num)//防止剩一个数时越界
end2 = num - 1;
while (begin1 <= end1 && begin2 <= end2)
{
if (dat[begin1] < dat[begin2])
{
tmp[index++] = dat[begin1++];
}
else
{
tmp[index++] = dat[begin2++];
}
}
while (begin1 <= end1)
{
tmp[index++] = dat[begin1++];
}
while (begin2 <= end2)
{
tmp[index++] = dat[begin2++];
}
for (int i = 0; i <= end2; i++)
{
dat[i] = tmp[i];
}
}
gap *= 2;//每次间隙翻两倍
}
free(tmp);
}
以上就是较重要的两大排序,请多多支持,点赞+转发,感激不尽