排序算法算是比较基本的算法,同时也是最重要的算法,涉及到的知识也比较多,下面记录一下各种排序算法的实现,包括插入排序,选择排序,快速排序,归并排序,冒泡排序等常见的排序算法:
1、插入排序:
插入排序的原理是每次将一个数插入到有序的集合中,从算法实现的角度讲,就是进行N趟遍历,没次将第i个数插入到前面有序的集合中,最后达到有序。从这我们可以看出算法的复杂度是O(N^2),在实现时将第i个数与前面的i-1个数进行比较,如果小于就交换,最后插入到合适的位置。
void insert_sort(int a[], int n)
{
for(int i = 1; i < n; i++)
{
for(int j = i - 1;j >=0, a[j] > a[j+1]; j--)
swap(a[j], a[j+1]);
}
}
2、选择排序
顾名思义,选择排序就是每次在候选集合中选择最小的数插入到候选结合的开头,并且不断的缩小候选集合的过程,从算法实现的角度讲,就是要进行N词遍历,每次在候选集合中选择最小的数放在候选集合前部的过程,并且不断的缩小候选集。
void select_sort(int a[], int n)
{
for(int i = 0; i < n; i++)
{
int min = i;
for(int j = i + 1; j < n; j++)
{
if(a[j] < a[min])
min = j;
}
swap(a[i], a[min]);
}
}
3、快速排序
快速排序是最常用的也算是经典的排序算法,它是通过分治递归的方式实现,通过选取哨兵,并将元素与哨兵比较,按照大小将数组切分成两部分,并对这两部分按照同样的方式进行递归计算,最后达到有序。
int quick_sort(int a[], int l, int h)
{
int i = l; int j = h; int x = a[l];
while(i < j)
{
while(i < j && a[j] >= x)
j--;
if(i < j)
a[i++] = a[j];
while(i < j && a[i] < x)
i++;
if(i < j)
a[j--] = a[i];
quick_sort(a, i+1, h);
quick_sort(a, l, i - 1);
}
a[i] = x;
}
4、归并排序
归并排序也是用分治递归的思想进行求解,想将小块进行排序,然后合并来实现,归并排序的算法复杂度是O(N*logN),空间复杂度是O(N)
void mergerArray(int a[], int first,int mid, int last, int tmp[])
{
int i = first, j = mid + 1, k = 0;
int m = mid, n = last;
while(i < m && j < n)
{
if(a[i] >= b[j])
tmp[k++] = b[j];
else
tmp[k++] = a[i];
}
while(i < m)
tmp[k++] = a[i++];
while(j < n)
tmp[j++] = b[j++];
for (i = 0; i < k; i++)
a[first + i] = temp[i];
}
void mergeSort(int a[], int first, int last, int tmp[])
{
if(first < last){
int mid = (first + last) / 2;
mergeSort(a, first, mid, tmp);
mergeSort(a, mid + 1, last, tmp);
mergerArray(a, first, mid, last, tmp);
}
}
5、冒泡排序
冒泡排序是O(N^2)复杂度的排序算法,效率较低,需要N趟遍历,每次将候选集中最小的数通过交换浮到最上面,也就是冒泡,还是很形象的。
void bubble_sort(int a[], int n)
{
for(int i = 0; i < n; i++)
{
for(j = 1; j < n -i; j++)
{
if(a[j -1] > a[j])
{
swap(a[j], a[j-1]);
}
}
}
}
冒泡算法也可以进行部分的改进,就是设置一个标志位,当交换不在发生的时候就可以认为排序已经结束,针对部分有序的数组还是可以加快排序速度的。