C++常见排序代码大全
文章目录
1.引言
我将按照一下常见排序给出相应的C++排序代码,并且必要时会给出非递归版本
代码全部经过本人测试且可用,走过路过不要错过,赶快收藏起来吧!
2.插入排序
2.1##直接插入排序##
时间复杂度:O(N*2)
稳定性:稳定
void DirectInsertSort(int* a, int n)
{
for (int i = 0; i < n - 1; i++)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + 1] = a[end];
--end;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
2.2##希尔排序##
时间复杂度:具体计算复杂,大约在O(N^1.3)左右
稳定性:不稳定
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;
for (int i = 0; i < n - gap; i++)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (tmp < a[end])
{
a[end +gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end +gap] = tmp;
}
}
}
3.选择排序
选择排序需要准备的Swap交换函数
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
3.1##直接选择排序##
时间复杂度:O(N*2)
稳定性:不稳定
void SelectSort(int* a, int n)
{
int begin = 0;
int end = n - 1;
while (begin < end)
{
int mini = begin, maxi = begin;
for (int i = begin+1; i <= end; i++)
{
if (a[i] > a[maxi])
{
maxi = i;
}
if (a[i] < a[mini])
{
mini = i;
}
}
Swap(&a[begin], &a[mini]);
if (maxi == begin) //防止maxi与begin重叠的情况出现
maxi = mini;
Swap(&a[end], &a[maxi]);
++begin;
--end;
}
}
3.2##堆排序##
时间复杂度:O(N*logN)
稳定性:不稳定
//小堆 升序
void AdjustDown(int* a,int n,int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
if (child + 1 <n && a[child + 1] > a[child])
{
++child;
}
if (a[parent] < a[child])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
void HeapSort(int*a,int n)
{
//从最后一个节点的父节点开始向前建堆
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(a, n, i);
}
int end = n-1;
while (end > 0)
{
Swap(&a[0], &a[end]);
AdjustDown(a, end, 0);
--end;
}
}
4.交换排序
4.1##冒泡排序##
时间复杂度:O(N*2)
稳定性:稳定
void BubbleSort(int* a, int n)
{
for (int j = 0; j < n; j++)
{
for (int i = 0; i < n; i++)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
}
}
}
}
4.2##快速排序##
时间复杂度:O(N*logN)
稳定性:不稳定
void QuickSort(int* a, int begin, int end)
{
if (begin >= end)
return;
int left = begin, right = end;
int keyi = left;
while (left < right)
{
//右边先走 找小
//必须加 left<right ,因为万一key值右边都比key大,就会走越界
//而且后面必须是<= 因为要找真小,不加=会出现相等情况,进而出现死循环
while (left < right && a[right] >= a[keyi])
{
right--;
}
//左边再走,找大
while (left < right && a[left] <= a[keyi])
{
left++;
}
Swap(&a[left], &a[right]);
}
Swap(&a[left], &a[keyi]);
//一定要更新keyi,准备下一次排序
keyi = left;
//递归左右子区间
QuickSort(a, begin, keyi - 1);
QuickSort(a, keyi + 1, end);
}
4.2.1快速排序优化之三数取中
//三数取中
int GetMidIndex(int* a,int begin,int end)
{
int mid = (begin + end) / 2;
if (a[begin] > a[mid])
{
if (a[begin] < a[end])
{
return begin;
}
else //a[begin] > a[end]
{
if (a[mid] > a[end])
{
return mid;
}
else
{
return end;
}
}
}
else//a[begin] < a[mid]
{
if (a[begin] > a[end])
{
return begin;
}
else //a[begin] < a[end]
{
if (a[mid] > a[end])
{
return end;
}
else
{
return mid;
}
}
}
}
4.2.2快速排序优化之小区间优化
在快排前面加上一个判断即可
void QuickSort(int* a, int begin, int end)
{
//------------小区间优化------------------
if (begin + end + 1 < 10) //小区间优化
{
DirectInsertSort(a + begin, end - begin + 1);
}
else
{
if (begin >= end)
return;
//三数取中
int mid = GetMidIndex(a, begin, end);
Swap(&a[begin], &a[mid]);
int left = begin, right = end;
int keyi = left;
while (left < right)
{
//右边先走 找小
//必须加 left<right ,因为万一key值右边都比key大,就会走越界
//而且后面必须是<= 因为要找真小,不加=会出现相等情况,进而出现死循环
while (left < right && a[right] >= a[keyi])
{
right--;
}
//左边再走,找大
while (left < right && a[left] <= a[keyi])
{
left++;
}
Swap(&a[left], &a[right]);
}
Swap(&a[left], &a[keyi]);
//一定要更新keyi,准备下一次排序
keyi = left;
//递归左右子区间
QuickSort(a, begin, keyi - 1);
QuickSort(a, keyi + 1, end);
}
}
4.3##快速排序(非递归)##
//单趟快排写出来,准备写快排非递归
int PartQuickSort(int* a, int begin, int end)
{
int left = begin, right = end;
int keyi = left;
while (left < right)
{
//先走右 找小
while (left < right && a[right] >= a[keyi])
{
right--;
}
while (left < right && a[left] <= a[keyi])
{
left++;
}
Swap(&a[left], &a[right]);
}
Swap(&a[left], &a[keyi]);
//一定要更新keyi,准备下一次排序
keyi = left;
return keyi;
}
//-------快排非递归:借助栈----------
void QuickSortNonR(int* a,int begin,int end)
{
stack<int> st;
st.push(begin);
st.push(end);
while (!st.empty()) //栈不为空
{
int right = st.top();
st.pop();
int left = st.top();
st.pop();
int keyi = PartQuickSort(a, left, right);
//入分区间
if (keyi + 1 < right)
{
st.push(keyi + 1);
st.push(right);
}
if (left < keyi - 1)
{
st.push(left);
st.push(keyi - 1);
}
}
}
5.归并排序
5.1##归并排序##
时间复杂度:O(N*logN)
稳定性:稳定
void _MergeSort(int* a, int begin,int end, int* tmp)
{
if (begin >= end)
return;
int mid = (begin + end) / 2;
_MergeSort(a, begin, mid, tmp);
_MergeSort(a, mid+1, end, tmp);
int begin1 = begin, end1 = mid;
int begin2 = mid + 1, end2 = end;
int i = begin;
//把两者小的往tmp中放
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
{
tmp[i++] = a[begin1++];
}
else
{
tmp[i++] = a[begin2++];
}
}
//再把两者剩下的走完即可
while (begin1 <= end1)
{
tmp[i++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[i++] = a[begin2++];
}
memcpy(a + begin, tmp + begin, sizeof(int)*(end - begin + 1));
}
void MergeSort(int* a, int n)
{
int* tmp = new int[sizeof(int)*n];
_MergeSort(a, 0, n - 1, tmp);
delete[] tmp;
tmp = nullptr;
}
5.2##归并排序(非递归)##
void MergeSortNonR(int* a, int n)
{
int* tmp = new int[sizeof(int) * n];
int rangeN = 1;
while (rangeN < n)
{
for (int i = 0; i < n; i += 2 * rangeN)
{
int begin1 = i, end1 = i + rangeN - 1;
int begin2 = i + rangeN, end2 = i + 2 * rangeN - 1;
int j = i;
//如果数组个数不是2的指数倍,那么则会分配区间不均匀,那么就会有越界的风险
//越界区间需要修正一下
//end1 begin1 end2 越界
if (end1 >= n)
{
end1 = n - 1;
begin2 = n;
end2 = n - 1;
}
//begin2 end2 越界
else if (begin2 >= n)
{
begin2 = n;
end2 = n - 1;
}
//只有end2越界
else if (end2 >= n)
{
end2 = n - 1;
}
//修正完正常走
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] <= a[begin2])
{
tmp[j++] = a[begin1++];
}
else
{
tmp[j++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[j++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[j++] = a[begin2++];
}
}
memcpy(a, tmp, sizeof(int) * n);
rangeN *= 2;
}
delete[] tmp;
tmp = nullptr;
}
else if (begin2 >= n)
{
begin2 = n;
end2 = n - 1;
}
//只有end2越界
else if (end2 >= n)
{
end2 = n - 1;
}
//修正完正常走
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] <= a[begin2])
{
tmp[j++] = a[begin1++];
}
else
{
tmp[j++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[j++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[j++] = a[begin2++];
}
}
memcpy(a, tmp, sizeof(int) * n);
rangeN *= 2;
}
delete[] tmp;
tmp = nullptr;
}