1.快速排序
首选选择一个key值,一般选择数组中第一个作为key值,再定义两个变量L,R。R从右向左找比key小的值,L从左到右找比key大的值,都找到后,进行交换。当L和R相遇后,将此位置的的数与key值交换。然后再把key值左边的区间和右边的区间重复上述步骤。
hoare版本:
void quicksort(int* a, int left,int right)//简单版快排
{
if (left >= right)
{
return;
}
int key = left;
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && a[end] >= a[key])
{
end--;
}
while (begin < end && a[begin] <= a[key])
{
begin++;
}
swap(a[begin], a[end]);
}
swap(a[key], a[begin]);
key = begin;
quicksort(a, left, key-1);
quicksort(a, key+1, right);
}
缺点:
当数组有序时,可能会引起栈溢出,会退化为的时间复杂度
解决方法:
1.三数取中(最左侧的数,最右侧的书,中间的数)取这三个数大小为中间的值作为key值
//三数取中
void quicksort(int* a, int left,int right)//简单版快排
{
if (left >= right)
{
return;
}
int mid = getmidnum(a, left, right);
swap(a[left], a[mid]);
int key = left;
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && a[end] >= a[key])
{
end--;
}
while (begin < end && a[begin] <= a[key])
{
begin++;
}
swap(a[begin], a[end]);
}
swap(a[key], a[begin]);
key = begin;
quicksort(a, left, key-1);
quicksort(a, key+1, right);
}
int getmidnum(int* a, int left, int right)
{
int mid = (left + right) >> 1;
if (a[left] < a[mid])
{
if (a[mid] < a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return right;
}
else
{
return left;
}
}
else
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return left;
}
else
{
return right;
}
}
}
2.小区间优化
void Insertsort(int* a, int n)
{
for (int i = 0; i + 1 < n; 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;
}
}
int getmidnum(int* a, int left, int right)
{
int mid = (left + right) >> 1;
if (a[left] < a[mid])
{
if (a[mid] < a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return right;
}
else
{
return left;
}
}
else
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return left;
}
else
{
return right;
}
}
}
void quicksort(int* a, int left,int right)//简单版快排
{
if (left >= right)
{
return;
}
if (right - left+1 < 10)//小区间优化,减少递归次数
{
Insertsort(a + left, right - left + 1);
}
else
{
int mid = getmidnum(a, left, right);//三数取中
swap(a[left], a[mid]);
int key = left;
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && a[end] >= a[key])
{
end--;
}
while (begin < end && a[begin] <= a[key])
{
begin++;
}
swap(a[begin], a[end]);
}
swap(a[key], a[begin]);
key = begin;
quicksort(a, left, key - 1);
quicksort(a, key + 1, right);
}
}
非递归写法:(使用栈)
int getmidnum(int* a, int left, int right)//三数取中
{
int mid = (left + right) >> 1;
if (a[left] < a[mid])
{
if (a[mid] < a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return right;
}
else
{
return left;
}
}
else
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return left;
}
else
{
return right;
}
}
}
int part1sort(int* a, int left, int right)//快排模板
{
int mid = getmidnum(a, left, right);
swap(a[left], a[mid]);
int key = left;
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && a[end] >= a[key])
{
end--;
}
while (begin < end && a[begin] <= a[key])
{
begin++;
}
swap(a[begin], a[end]);
}
swap(a[key], a[begin]);
return begin;
}
void quicksortNonR(int* a, int left, int right)//非递归快排
{
stack<int>st;
st.push(right);
st.push(left);
while (st.size())
{
int begin = st.top();
st.pop();
int end = st.top();
st.pop();
int key = part1sort(a, begin, end);
if (key + 1 < end)
{
st.push(end);
st.push(key + 1);
}
if (begin < key - 1)
{
st.push(key - 1);
st.push(begin);
}
}
}
归并排序:
void _guisort(int* a, int* tmp, int begin, int end)
{
if (begin >= end)
{
return;
}
int mid = (begin + end) / 2;
_guisort(a, tmp, begin, mid);
_guisort(a, tmp, mid+1, end);
int begin1 = begin, end1 = mid;
int begin2 = mid+1, end2 = end;
int i = begin;
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, (end - begin + 1) * sizeof(int));
}
void guisort(int* a, int n)
{
int* temp = (int*)malloc(sizeof(int) * n);
_guisort(a, temp, 0, n - 1);
}
非递归归并排序:
void guisortNonr(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
int gap = 1;//每组归并的数字个数
while (gap<n)
{
for (int i = 0; i < n; i += 2 * gap)
{
int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;
if (begin2 >=n)
{
break;
}
if (end2 >= n)
{
end2 = n - 1;
}
int j = i;
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 + i, tmp + i, sizeof(int) * (end2 - i + 1));
}
gap = gap * 2;
}
}
本篇完