几个排序算法实例
两个月没有更新博客了,今天重温一下几个常用的排序算法。
快速排序
快速排序是使用率极高的排序方法,属于分治法的一种,基本思想是先定一个基准数,通过一轮比较,把比基准数小的放在一边,比基准数大的放在另一边,从而形成了两个数列,然后分别对两边的数,递归进行上述过程,直至排序结束。
#include <stdio.h>
void QuickSort(int s[], int low, int high);
void Swap(int *a, int *b);
int main(void)
{
int i, size;
int s[] = {1, 5, 7, 3, 2, 9, 0, 8, 4, 6};
size = sizeof(s) / sizeof(s[0]);
QuickSort(s, 0, 9);
for(i = 0; i < size; i++)
printf("%d ", s[i]);
printf("\n");
}
void QuickSort(int s[], int low, int high)
{
int i, last;
if(low < high) {
last = low;
for(i = low + 1; i <= high; i++) {
if(s[i] < s[low])
Swap(&s[i], &s[++last]);
}
Swap(&s[last], &s[low]);
QuickSort(s, low, last - 1);
QuickSort(s, last + 1, high);
}
}
void Swap(int *a, int *b)
{
if(a != b) {
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
}
冒泡排序与选择排序
冒泡排序是逻辑最简单的排序之一,通过两层循环,相邻的数两两比较,把较大的放在后面,最多n-1轮之后,排序完成。 比较有意思的是,对比选择排序,可以发现两者的代码非常相似,选择排序是两层循环,但不是相邻的数进行比较,而是每一轮都寻找最小的一个数放在前面,然后在剩下的数中继续寻找最小的数排在第二位,直至排序完成。
#include <stdio.h>
void BubbleSort(int s[], int size);
void SelectSort(int s[], int size);
void Swap(int *a, int *b);
int main(void)
{
int i, size;
int s[] = {1, 6, 8, 9, 0, 8, 5, 4, 3, 2};
size = sizeof(s) / sizeof(s[0]);
//BubbleSort(s, size);
SelectSort(s, size);
for(i = 0; i < size; i++)
printf("%d ", s[i]);
printf("\n");
}
void BubbleSort(int s[], int size)
{
int i, j;
for(i = 0; i < size -1; i++) {
for(j = 0; j < size - 1 - i; j++) {
if(s[j] > s[j + 1])
Swap(&s[j], &s[j + 1]);
}
}
}
void SelectSort(int s[], int size)
{
int i, j;
for(i = 0; i < size; i++) {
for(j = i + 1; j < size; j++) {
if(s[j] < s[i])
Swap(&s[j], &s[i]);
}
}
}
void Swap(int *a, int *b)
{
if(a != b) {
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
}
直接插入排序
直接插入排序,每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。 第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
#include <stdio.h>
void InsertSort(int s[], int size);
int main(void)
{
int i, size;
int s[] = {1, 4, 6, 8, 9, 0, 2, 3, 5, 7};
size = sizeof(s) / sizeof(s[0]);
InsertSort(s, size);
for(i = 0; i < size; i++)
printf("%d ", s[i]);
printf("\n");
}
void InsertSort(int s[], int size)
{
int i, j, k, temp;
for(j = 1; j < size; j++) {
i = 0;
while(s[i] < s[j] && i < j)
i++;
if(i != j) {
temp = s[j];
for(k = j; k > i; k--)
s[k] = s[k - 1];
s[i] = temp;
}
}
}
堆排序
堆排序,这里讨论的是最大堆,父结点比左右孩子都要大,堆顶一定是所有元素中的最大值,因此可以快速地得到元素中的最大值。另外,堆的存储我们用数组来表示,父节点为i,左孩子就是2i+1,右孩子为2i+2。进行堆排序一般有三个过程:
堆调整:比较父节点和左右孩子,如果左右孩子比根节点的值大,则进行交换,以满足堆的定义
建立堆:数据一开始可以看作是无序的完全二叉树,建立堆就是对所有的非叶子节点进行堆调整
堆排序:首先建立堆,然后交换根节点与最后一个叶子节点,交换之后把最后的叶子节点当作是有序数组,然后循环上述过程,重新对剩下的数进行堆调整,并依次把最大数交换到叶子节点中。最后,形成有序数组。
#include <stdio.h>
void Swap(int *a, int *b);
void HeapSort(int s[], int size);
void BuildHeap(int s[], int size);
void HeapAdjust(int s[], int i, int size);
int main(void)
{
int i, size;
int s[] = {1, 4, 6, 8, 0, 9, 2, 3, 5, 7};
size = sizeof(s) / sizeof(s[0]);
HeapSort(s, size);
for(i = 0; i < size; i++)
printf("%d ", s[i]);
printf("\n");
}
void HeapAdjust(int s[], int i, int size)
{
int lchild = 2 * i + 1;
int rchild = 2 * i + 2;
int max = i;
if(i <= size / 2) {
if(lchild <= size && s[lchild] > s[max])
max = lchild;
if(rchild <= size && s[rchild] > s[max])
max = rchild;
if(max != i) {
Swap(&s[max], &s[i]);
HeapAdjust(s, max, size);
}
}
}
void BuildHeap(int s[], int size)
{
int i;
for(i = size / 2; i >= 0; i--)
HeapAdjust(s, i, size);
}
void HeapSort(int s[], int size)
{
int i;
BuildHeap(s, size);
for(i = size - 1; i >= 0; i--) {
Swap(&s[i], &s[0]);
HeapAdjust(s, 0, i - 1);
}
}
void Swap(int *a, int *b)
{
if(a != b) {
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
}
归并排序
归并排序的思想是,把两个有序数列合并成一个有序的数列,而产生有序数列的方法是不断地进行分隔,当每一个数列都只有一个数的时候,即可认为是有序的,然后循环地把这些有序数列合并起来。
#include <stdio.h>
void MergeSort(int s[], int low, int high, int temp[]);
void MergeArray(int s[], int low, int mid, int high, int temp[]);
int main(void)
{
int i;
int s[] = {1, 3, 5, 7, 9, 2, 4, 6, 8};
size = sizeof(s) / sizeof(s[0]);
int p[size];
MergeSort(s, 0, size - 1, p);
for(i = 0; i < size; i++)
printf("%d ", s[i]);
printf("\n");
}
void MergeSort(int s[], int low, int high, int temp[])
{
if(low < high) {
int mid = (low + high) / 2;
MergeSort(s, low, mid, temp);
MergeSort(s, mid + 1, high, temp);
MergeArray(s, low, mid, high, temp);
}
}
//合并有序数列
void MergeArray(int s[], int low, int mid, int high, int temp[])
{
int k = 0;
int i = low;
int j = mid + 1;
while(i <= mid && j <= high) {
if(s[i] <= s[j]) {
temp[k++] = s[i++];
}
else {
temp[k++] = s[j++];
}
}
while(i <= mid)
temp[k++] = s[i++];
while(j <= high)
temp[k++] = s[j++];
for(i = 0; i < k; i++)
s[low + i] = temp[i];
}
Author:leung
25 Nov 2014
← Home comments powered by Disqus