排序算法总结
最近在看算法导论,结合网上的信息总结一下排序算法。
相关文章:
http://blog.csdn.net/xiazdong/article/details/8462393
关于算法的不稳定性不是很理解,需要进一步加强。
https://visualgo.net/
很形象
int a[n] = { 6, 9, 2, 1 };
int b[n] = { 1, 2, 6, 9 };
int c[n] = { 9, 6, 2, 1 };
插入排序
void insert_sort(int arr[])
{
cout << "insert sort: "<<endl;
for (int i = 1; i < n; ++i)
{
int j = i - 1;
int key = arr[i];
while (j>=0 && arr[j] > key)
{
arr[j + 1] = arr[j];//将key之前的序列中大于key的值向后移动一位
--j;
}
arr[j + 1] = key;//将key移动到前边没有比key大的值得位置上
print_arr(arr);
}
}
6 9 2 1
6 9 2 1 ->6 9 2 1
6 9 2 1 ->2 6 9 1
2 6 9 1 ->1 2 6 9
冒泡排序
void bubble_sort(int a[])
{
cout << "bubble_sort: " << endl;
int temp;
for (int i = 0; i < n-1; ++i)
{
for (int j = n-1; j > i; --j)//要逆着排,这样才能把最小的排在最前边
{
if (a[j] < a[j-1])
{
temp = a[j];
a[j] = a[j-1];
a[j-1] = temp;
}
print_arr(a);
}
}
}
6 9 2 1
6 9 2 1 -> 6 9 1 2
6 9 1 2 -> 6 1 9 2
6 1 9 2 -> 1 6 9 2
1 6 9 2 -> 1 6 2 9
1 6 2 9 -> 1 2 6 9
1 2 6 9 -> 1 2 6 9
选择排序
void select_sort(int a[])
{
cout << "select sort: " << endl;
for (int i = 0; i < n - 1; ++i)
{
int min = i;
for (int j = i + 1; j < n; ++j)
{
if (a[j] < a[min])
min = j;
}
swap(a[i], a[min]);
print_arr(a);
}
}
6 9 2 1
6 9 2 1 ->6 9 2 1
6 9 2 1 ->2 9 6 1
2 9 6 1 ->1 9 6 2
1 9 6 2 ->1 6 9 2
1 6 9 2 ->1 2 9 6
1 2 9 6 ->1 2 6 9
/快速排序
int partition(int a[], int p, int q)
{
int i = p - 1;
int pivot = a[q];
for (int j = p; j < q ; ++j)
{
if (a[j] <= pivot)
{
i++;
swap(a[i], a[j]);//让子序列中的小于pivot的数放在前边
}
}
swap(a[i + 1], a[q]);
return i + 1;
}
void rescursive_quicksort(int a[], int p, int q)
{
if (p < q)
{
int r = partition(a, p, q);
rescursive_quicksort(a, p, r-1);
rescursive_quicksort(a, r + 1, q);
print_arr(a);
}
}
void quick_sort(int a[])
{
rescursive_quicksort(a, 0, n-1);
}
归并排序
void merge(int a[], int p, int q, int m)
{
int n1 = m - p + 1;
int n2 = q - m;
int *left = new int[n1];
int *right = new int[n2];
for (int i = 0; i < n1; ++i)
left[i] = a[p + i];
for (int i = 0; i < n2; ++i)
right[i] = a[m + i +1];
////////////合并/////////
int i = 0;
int j = 0;
int k = p;
while (i<n1 && j < n2 && k<n)
{
if (left[i] < right[j])
a[k++] = left[i++];
else
a[k++] = right[j++];
}
while (i < n1) /* left[] is not exhausted */
a[k++] = left[i++];
while (j < n2) /* right[] is not exhausted */
a[k++] = right[j++];
print_arr(a);
}
void recursive_merge_sort(int a[], int p, int q)
{
if (p < q)
{
int m = (p + q) / 2 ;
recursive_merge_sort(a, p, m);
recursive_merge_sort(a, m + 1, q);
merge(a, p, q, m);
print_arr(a);
}
}
void merge_sort(int a[])
{
cout << "merge sort: " << endl;
recursive_merge_sort(a, 0, n - 1);
}
堆排序
两部分:(1) 形成最大堆(最顶端数最大),从底部向上计算
(2)将top移到最末,对于0~n-2的数组进行处理,形成新的最大堆
void heap_adjust(int a[], int s, int length)//序号s为根节点
{
int temp = a[s];
int child = 2 * s + 1;
while (child < length)
{
if (child + 1<length && a[child]<a[child + 1])//比较两个子节点大小,得到值大的子节点
++child;
if (a[s] < a[child])//如果根节点的值小于子节点的值,替换值并且更新根节点
{
a[s] = a[child];
s = child;
child = 2 * s + 1;
}
else
break;
a[s] = temp;//给以前的子节点(新的根节点赋原根节点的值)
}
print_arr(a);
}
void build_max_heap(int a[])
{
for (int i = (n - 1) / 2; i >= 0; --i)//i为根节点序号,从底部算到上部
heap_adjust(a, i, n);
}
void heap_sort(int a[])
{
build_max_heap(a);
for (int i = n - 1; i > 0; --i)
{
int temp = a[i];//把最后的值与第一个值(最大)替换
a[i] = a[0];
a[0] = temp;
heap_adjust(a, 0, i);///对0~i的长度的堆进行调整
}
print_arr(a);
}
希尔排序
变步长的插入排序,这里我用的步长为n/2,n/4,…1
void shell_sort(int a[])
{
for (int step = n; step > 0; step=step/2)//变步长的插入排序
{
for (int i = step; i < n; ++i)
{
int key = a[i];
int j = i-step;
while ( j>= 0 && a[j]>key)
{
a[j + step] = a[j];
j=j-step;
}
a[j + step] = key;
}
print_arr(a);
}
}
计数排序
开辟一个count计数数组,统计原数组各个数的频数,累加得到累积频数,减一即在新数组中的位置。
void counting_sort(int a[],int k)
{
//int max = 0;
//for (int i = 0; i<n; ++i)
//{
// if (a[i]>max)
// max = a[i];
//}
//k = max + 1;
int *count = new int[k];
int *b = new int[n];
for (int i = 0; i < k; ++i)
count[i]=0;
for (int i = 0; i < n; ++i)
++count[a[i]];
for (int i = 1; i < k; ++i)//从1开始算哦
count[i] = count[i] + count[i - 1];//统计不比a[i]大的数的个数,就是a[i]在新的数组中的位置
for (int i = n-1; i >=0; --i)
{
count[a[i]]--;//先减1,从零开始计数
b[count[a[i]]] = a[i];
}
print_arr(b);
delete count;
delete b;
}
基数排序
先比个位(计数排序),然后依次十位,百位…
int* getBit(int a[], int bit_num)
{
int* b=new int[n];
for (int i = 0; i < n; ++i)
{
int total_bit_num = 0;
for (int no = a[i]; no > 0; no = no / 10)
total_bit_num++;
int p = pow(10, bit_num);
b[i] = a[i] /p %10;
}
return b;
}
void radix_sort(int a[])
{
int max = find_max(a);
int bit_num = 0;
for (int i = max; i > 0; i = i / 10)
bit_num++;
int *num;
int *temp = new int[n];
int count[10];
for (int j = 0; j < bit_num; ++j)
{
for (int i = 0; i < 10; ++i)//清空计数数组
count[i] = 0;
num = getBit(a, j);//得到个位,十位...
for (int i = 0; i < n; ++i)
++count[num[i]];
for (int i = 1; i < 10; ++i)//从1开始算哦
count[i] = count[i] + count[i - 1];//统计不比a[i]大的数的个数,就是a[i]在新的数组中的位置
for (int i = n-1; i >= 0 ; --i)//倒计算,假设两个相同的3正序算,第一个3会被放在后边,打乱了以前的排序
{
temp[count[num[i]]-1] = a[i];//先减1,从零开始计数
count[num[i]]--;
}
for (int i = 0; i < n; ++i)
a[i] = temp[i];
print_arr(a);
}
delete num;
delete temp;
}