十个经典排序算法
十个经典排序算法
快排
/* 快速排序 */
#include <iostream>
#include <cstdlib>
#define N 6
using namespace std;
void quick_sort(int arr[], int begin, int end);
void print_arr(int arr[], int n);
int main()
{
int arr[N] = {10, 4,7, 10, 4,7};
cout << "排序前:" << endl;
print_arr(arr, N);
quick_sort(arr, 0, N);
cout << "排序后:" << endl;
print_arr(arr, N);
}
// 不包含 end
void quick_sort(int arr[], int begin, int end)
{
if (end - begin <= 1)
return;
swap(arr[begin], arr[(begin + end) / 2]);
int pivot = arr[begin];
int i = begin + 1;
int j = end - 1;
while (i < j)
{
while (i < end - 1 && arr[i] < pivot)
i++;
while (j > begin && arr[j] > pivot)
j--;
if (i < j)
swap(arr[i], arr[j]);
}
if (j < i)
swap(arr[j], arr[begin]);
quick_sort(arr, begin, j);
quick_sort(arr, j + 1, end);
}
void print_arr(int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}
快排的要点
i 和 j 的关系
当 i < j 时,才能进行循环的移动和交换
每次让 i 指向从左到右,大于 pivot 的数
每次让 j 指向从右到左,小于 pivot 的数
当循环结束时,j 有两种情况,一种是 等于 i 一种是 小于 i
如果 j == i 的话,那么说明此时已经是有序了,不用再进行调换,如果调换反而会打乱顺序
如果 j < i 的话,说明 j 指向的是最后一个小于 pivot 的数,让他们换个位置
归并排序
/*归并排序*/
#include <iostream>
#include <cstdlib>
#include <string>
#define N 10
using namespace std;
void merge_sort(int arr[], int begin, int end);
void print_arr(int arr[], int n);
int main()
{
int arr[N] = {1,2,1,1,2,1,1,2,1,87};
cout << "排序前:" << endl;
print_arr(arr, N);
merge_sort(arr, 0, N);
cout << "排序后:" << endl;
print_arr(arr, N);
}
void merge_sort(int arr[], int begin, int end)
{
if (end - begin <= 1)
return;
int * new_arr = new int[end - begin];
merge_sort(arr, begin, (begin + end) / 2);
merge_sort(arr, (begin + end) / 2, end);
int i = begin;
int j = (begin + end) / 2;
int k = 0;
while (i < (begin + end) / 2 && j < end)
new_arr[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
while (i < (begin + end) / 2)
new_arr[k++] = arr[i++];
while (j < end)
new_arr[k++] = arr[j++];
while (k)
arr[begin + k - 1] = new_arr[--k];
delete new_arr;
}
void print_arr(int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}
归并排序主要要注意的就是要造个新数组,把两个已经有序的子数组依次按从小到大放到新数组里面
计数排序
/* 计数排序 */
#include <iostream>
#include <cstdlib>
#define N 10
using namespace std;
void count_sort(int arr[], int n);
void print_arr(int arr[], int n);
int main()
{
int arr[N] = {5,4,3,2,1,5,4,3,2,1};
cout << "排序前:" << endl;
print_arr(arr, N);
count_sort(arr, N);
cout << "排序后:" << endl;
print_arr(arr, N);
}
void count_sort(int arr[], int n)
{
int max = arr[0];
for (int i = 0; i < n; i++)
if (arr[i] > max)
max = arr[i];
int * count = (int * )calloc(max + 1, sizeof(int)); // count 数组存放 0-max 每个数出现的次数
for (int i = 0; i < n; i++)
count[arr[i]]++;
for (int i = 1; i <= max; i++)
count[i] += count[i-1];
int curr = 0;
int i = 0;
while (curr <= max)
{
while (count[curr] > i)
arr[i++] = curr;
curr++;
}
}
void print_arr(int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}
希尔排序
/* shell 排序 */
#include <iostream>
#include <cstdlib>
#define N 3
using namespace std;
void shell_sort(int arr[], int n);
void print_arr(int arr[], int n);
void bubble_sort(int arr[], int n, int begin, int step);
int main()
{
int arr[N] = {1,2,0};
cout << "排序前:" << endl;
print_arr(arr, N);
shell_sort(arr, N);
cout << "排序后:" << endl;
print_arr(arr, N);
}
void shell_sort(int arr[], int n)
{
for (int step = n/2; step > 0; step /= 2)
for (int i = 0; i < step; i++)
bubble_sort(arr, n, i, step);
}
void print_arr(int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}
void bubble_sort(int arr[], int n, int begin, int step)
{
bool changed = false;
for (int i = begin; i < n; i += step)
{
changed = false;
for (int j = begin; j < n - step; j += step)
{
if (arr[j] > arr[j + step])
{
int temp = arr[j + step];
arr[j + step] = arr[j];
arr[j] = temp;
changed = true;
}
}
if (!changed)
break;
}
}
堆排序
堆排序很好
/* 堆排序 */
#include <iostream>
#include <cstdlib>
#define N 12
using namespace std;
void heap_sort(int arr[], int n);
void print_arr(int arr[], int n);
void heapify(int arr[], int n);
int main()
{
int arr[N] = {5,4,3,2,1,5,4,7,8,3,2,1};
cout << "排序前:" << endl;
print_arr(arr, N);
heap_sort(arr, N);
cout << "排序后:" << endl;
print_arr(arr, N);
}
void heap_sort(int arr[], int n)
{
heapify(arr, n);
for (int i = n; i > 1; i--)
{
swap(arr[i - 1], arr[0]);
heapify(arr, i - 1);
}
}
//完全二叉树 编号从1开始
void heapify(int arr[], int n)
{
for (int i = 2; i <= n; i++)
for (int j = i; j > 1; j /= 2)
if (arr[j - 1] > arr[j/2 - 1])
swap(arr[j - 1], arr[j/2 - 1]);
}
void print_arr(int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}