最近重新回顾了一下数据结构和算法的一些基本知识,简单整理下C语言下的常见排序算法。
选择排序selectSort
选择排序是最简单的一种基于O(n2)时间复杂度的排序算法,基本思想是从i=0位置开始到i=n-1每次通过内循环找出i位置到n-1位置的最小(大)值
void selectSort(int arr[], int n)
{
int i, j , minValue, tmp;
for(i = 0; i < n-1; i++)
{
minValue = i;
for(j = i + 1; j < n; j++)
{
if(arr[minValue] > arr[j])
{
minValue = j;
}
}
if(minValue != i)
{
tmp = arr[i];
arr[i] = arr[minValue];
arr[minValue] = tmp;
}
}
}
void printArray(int arr[], int n)
{
int i;
for(i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void main()
{
int arr[10] = {2,5,6,4,3,7,9,8,1,0};
printArray(arr, 10);
selectSort(arr, 10);
printArray(arr, 10);
return;
}
快速排序quickSort
快速排序思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
#include <stdio.h>
void printArray(int arr[], int n)
{
int i;
for(i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return;
}
void swap(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
return;
}
static void _quickSort3(int arr [ ],int l,int r)
{
int i, lt, gt;
if(l >= r)
{
return;
}
i = l + 1;
lt = l;
gt = r ;
while(i <= gt)
{
if(arr[i] < arr[l])
{
swap(&arr[lt + 1], &arr[i]);
lt ++;
i++;
}
else if(arr[i] > arr[l])
{
swap(&arr[i], &arr[gt]);
gt--;
}
else
{
i++;
}
}
swap(&arr[l], &arr[gt]);
_quickSort3(arr, l, lt);
_quickSort3(arr, gt + 1, r);
return;
}
void quickSort(int arr[], int n)
{
_quickSort3(arr, 0, n - 1);
return;
}
void main()
{
int arr[10] = {1,5,9,8,7,6,3,4,0,2};
printArray(arr, 10);
quickSort(arr, 10);
printArray(arr, 10);
}
冒泡排序 bubbleSor
冒泡排序在一组需要排序的数组中,对两两数据顺序与要求顺序相反时,交换数据,使大的数据往后移,每趟排序将最大的数放在最后的位置上。
void bubbleSort(int arr[], int n)
{
int i, nflag, tmp;
do
{
nflag = 0;
for(i = 0; i < n - 1; i++)
{
if(arr[i] > arr[i + 1])
{
tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
nflag = i + 1;
}
}
n = nflag;
}while(nflag);
}
void printArray(int arr[], int n)
{
int i;
for(i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void main()
{
int arr[10] = {2,5,6,4,3,7,9,8,1,0};
printArray(arr, 10);
bubbleSort(arr, 10);
printArray(arr, 10);
return;
}
插入排序insertSort
插入排序是将一个记录插入到已经有序的序列中,得到一个新的元素加一的有序序列,实现上即将第一个元素看成一个有序的序列,从第二个元素开始逐个插入得到一个完整的有序序列
void insertSort(int arr[], int n)
{
int i, j, tmp;
for(i = 1; i < n; i++)
{
for(j = i; j > 0; j--)
{
if(arr[j] < arr[j-1])
{
tmp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = tmp;
}
else
{
break;
}
}
}
return;
}
void printArray(int arr[], int n)
{
int i;
for(i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return;
}
void main()
{
int arr[10] = {2,5,6,4,3,7,9,8,1,0};
printArray(arr, 10);
insertSort(arr, 10);
printArray(arr, 10);
return;
}
归并排序merge
归并排序是基于归并操作的一种排序算法,归并操作的原理就是将一组有序的子序列合并成一个完整的有序序列,即首先需要把一个序列分成多个有序的子序列,通过分解到每个子序列只有一个元素时,每个子序列都是有序的,在通过归并各个子序列得到一个完整的序列
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void merge(int arr[], int l, int mid, int r)
{
int len,i, pl, pr;
int *tmp = NULL;
len = r - l + 1;
tmp = (int*)malloc(len * sizeof(int)); //申请存放完整序列内存
memset(tmp, 0x0, len * sizeof(int));
pl = l;
pr = mid + 1;
i = 0;
while(pl <= mid && pr <= r) //两个子序列都有值,比较最小值
{
if(arr[pl] < arr[pr])
{
tmp[i++] = arr[pl++];
}
else
{
tmp[i++] = arr[pr++];
}
}
while(pl <= mid) //左边子序列还有值,直接拷贝到新序列中
{
tmp[i++] = arr[pl++];
}
while(pr <= r) //右边子序列还有值
{
tmp[i++] = arr[pr++];
}
for(i = 0; i < len; i++)
{
arr[i+l] = tmp[i];
}
free(tmp);
return;
}
int min(int x, int y)
{
return (x > y)? y : x;
}
/*
归并完成的条件是得到子序列长度等于n,用sz表示当前子序列的长度。从1开始每次翻倍直到等于n。根据上面归并的方法,从i=0开始分组,下一组坐标应该i + 2*sz,第i组第一个元素为arr[i],最右边元素应该为arr[i+2*sz -1],遇到序列最右边元素不够分组的元素个数时应该取n-1,中间的元素为arr[i+sz -1],依次类推进行归并得到完整的序列
*/
void mergeSortBu(int arr[], int n)
{
int sz, i, mid,l, r;
for(sz = 1; sz < n; sz+=sz)
{
for(i = 0; i < n - sz; i += 2*sz)
{
l = i;
r = i + sz + sz;
mid = i + sz -1;
merge(arr, l, mid, min(r-1, n-1));
}
}
return;
}
void printArray(int arr[], int n)
{
int i;
for(i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
return;
}
void main()
{
int arr[10] = {2,5,6,4,3,7,9,8,1,0};
printArray(arr, 10);
mergeSortBu(arr, 10);
printArray(arr, 10);
return;
}
另一种是通过递归的方式,递归方式可以理解为至顶向下的操作,即先将完整序列不停分解为子序列,然后在将子序列归并为完整序列。
递归算法实现:
void mergeSort(int arr[], int l, int r)
{
if(l >= r)
{
return;
}
int mid = (l + r)/2;
mergeSort(arr, l, mid);
mergeSort(arr, mid+1, r);
merge(arr, l, mid, r);
return;
}