排序
    排序算法的稳定性:当序列中有相同的数据量,算法会不会改变这两个数据的前后位置。
    冒泡排序:是一种稳定排序,在排序过程中可以监测到数据是否已经有序,可以立既停止,如果待排序的数据基本有序,则冒泡的效率是非常高的。相关参考:百度百科     插入排序:当一列已经有序,再有加入的数据时,适合使用插入排序。相关参考:百度百科     选择排序:是冒泡排序的一种变种,但是它没有冒泡对数据有序性的敏感,但它在排序过程中比较冒泡要少了很多数据交换,因此数据比较混乱的情况下要比冒泡要快。相关参考:百度百科     快速排序:一种基于交换的算法,相关参考:百度百科

    堆排序
        首先把数据当作完全二叉树,然后保证根结点最大,然后把根结点与最后一个元素交换,然后再调整二叉树(逐渐减少数组),让根依然保持最大,重复上次操作。相关参考:百度百科     归并排序
        不交换数据,但需要借助额外的空间,用作临时的存储空间。

快速排序希尔排序直接选择排序堆排序是不稳定的排序算法,而基数排序冒泡排序直接插入排序折半插入排序归并排序基数排序是稳定的排序算法。

算法的时间复杂度
    注意:时间复杂度并不是指算法运行所需要的时间,而是算法执行的次数。
    冒泡排序:O(N),O(N^2)
    插入排序:O(N),O(N^2)
    选择排序:O(N^2)
    快速排序:O(nlog2n)
    堆排序:O(nlog2n)
    归并排序:O(nlog2n)

 

算法实现如下(C语言):

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define swap(a,b) {typeof(a) t=a;a=b;b=t;}    // 宏定义swap

// 冒泡排序
void bubble_sort(int* arr,int len)    // 传入需要排序的数组及其长度
{
	for(int i=len-1; i>0; i--)    // 从尾位置往前走
	{
		bool flag = true;    // 如果发现已经有序,则循环结束
		for(int j=0; j<i; j++)    // 从头位置往i的前一个位置走
		{
			if(arr[j] > arr[j+1])    // 如果发现前一个数大于后一个(升序)
			{
				swap(arr[j],arr[j+1]);    // 就交换它们的数据
				flag = false;    // 如果存在交换,则置flag为false
			}
		}
		if(flag) break;    // 因为发生交换,所以还没有排好序
	}
}

// 插入排序
void insert_sort(int* arr,int len)
{
	for(int i=1; i<len; i++)    // 从1开始(因为j=i-1)
	{
		int index = -1;    // 记录要插入的位置
		int t = arr[i];    // 临时变量存储arr[i]
		for(int j=i-1; j>=0; j--)    // 从i的前一个位置走到0
		{
			if(t < arr[j])    // 如果前面的数大于临时变量t
			{
				arr[j+1] = arr[j];    // 元素后移
				index = j;    // 记录其下标
			}
		}
		if(index != -1)
			arr[index] = t;    // 将临时变量插入到最远位置
	}
}

// 选择排序
void select_sort(int* arr,int len)
{
	for(int i=len-1; i>0; i--)    // 从尾开始往前
	{
		int max = i;    // 存储最大数的坐标
		for(int j=0; j<i; j++)    // 从头开始往i-1的位置走
		{
			if(arr[j] > arr[max])    // 查找最大值
				max = j;    //记录下标
		}
		swap(arr[i],arr[max]);    // 当前值和最大值进行交换
	}
}

void _quick_sort(int* arr,size_t left,size_t right)
{
	if(left >= right) return;    // 左下标和右下标相遇或左下标在右下标的右边,排序完成
	int pi = (left+right)/2; //计算标杆的下标
	int pv = arr[pi];    // 备份标杆的值
	int l = left, r = right;    // 备份左右下标
	while(l < r)    // 左右下标相遇时结束
	{
		while(l < pi && arr[l] <= pv) l++;	// 在标杆的左边寻找比它大的数据
		if(l < pi)	// 如果没有超出范围,说明找到比标杆大的值
		{
			arr[pi] = arr[l];	// 与标杆交换位置,并记录新的标杆下标
			pi = l;
		}
		while(pi < r && arr[r] >= pv) r--;	// 
		if(pi < r)	// 如果没有超出范围,说明找到比标杆小的值
		{
			arr[pi] = arr[r];
			pi = r;
		}
		arr[pi] = pv;    // 还原标杆的值
		if(pi-left > 1) _quick_sort(arr,left,pi-1);    // 递归
		if(right-pi > 1) _quick_sort(arr,pi+1,right);

	}
}

// 快速排序
void quick_sort(int* arr,size_t len)
{
	_quick_sort(arr,0,len-1);
}

void create_heap(int* arr,size_t root,size_t len)
{
	if(root >= len) return;
	int left = root*2+1;    // 左子树的位置
	int right = root*2+2;    // 右子树的位置

	create_heap(arr,left,len);    // 递归
	create_heap(arr,right,len);

	int max = root;    // 设当前根结点为最大值
	if(left < len)
	{
		if(arr[left] > arr[max])    // 如果当前根的值大于max中的值
			max = left;    // 将此位置赋给max
	}
	if(right < len)
	{
		if(arr[right] > arr[max])    // 同理
			max = right;
	}
	if(max != root)    // 如果被修改过
		swap(arr[max],arr[root]);    // 交换当前根与最大值
}

// 堆排序
void heap_sort(int* arr,size_t len)
{
	for(int i=0; i<len; i++)
	{
		create_heap(arr,0,len-i);
		swap(arr[0],arr[len-i-1]);
	}
	//show_arr(arr,10);
}

// 归并排序
void merge(int* arr,size_t left,size_t pi,size_t right,int* temp)
{
	int i = left,j = pi+1,k = left;
	// 外部合并 (临时变量是外部提供的)
	while(i<=pi && j<=right)
	{
		if(arr[i] < arr[j])
			temp[k++] = arr[i++];
		else
			temp[k++] = arr[j++];
	}
	while(i<=pi) temp[k++] = arr[i++];
	while(j<=right) temp[k++] = arr[j++];
	for(int i=left; i<=right; i++)
	{
		arr[i] = temp[i];
	}
}

void _merge_sort(int* arr,size_t left,size_t right,int* temp)
{
	if(left >= right) return;
	int pi = (left+right)/2;
	_merge_sort(arr,left,pi,temp);
	_merge_sort(arr,pi+1,right,temp);
	merge(arr,left,pi,right,temp);
}

void merge_sort(int* arr,size_t len)
{	// 把元素差分成1个个,然后标杆左右两侧进行2块2块的比较
	int temp[len];
	_merge_sort(arr,0,len-1,temp);
}

void show_arr(int* arr,size_t len)
{
	for(int i=0; i<len; i++)
	{
		printf("%d ",arr[i]);
	}
}

int main()
{
	int arr[10],arr1[10],arr2[10];
	for(int i=0; i<10; i++)
	{
		arr[i] = rand() % 50;
		arr1[i] = rand() % 50;
		arr2[i] = rand() % 50;
	}
	printf("原序列arr:");
	show_arr(arr,10);
/*
	printf("\n原序列arr1:");
	show_arr(arr1,10);

	printf("\n原序列arr2:");
	show_arr(arr2,10);
	printf("\n");

	printf("\n冒泡排序:");
	bubble_sort(arr,10);
	show_arr(arr,10);
	printf("\n插入排序:");
	insert_sort(arr1,10);
	show_arr(arr1,10);
	printf("\n选择排序:");
	select_sort(arr2,10);
	show_arr(arr2,10);

	quick_sort(arr2,10);
	show_arr(arr2,10);
*/

//	heap_sort(arr,10);
	merge_sort(arr,10);
	printf("\n");
	show_arr(arr,10);
}

码云:传送门