常用排序算法—简单基本实现

直接插入排序 for-if-for

假定数组前面有序,将待排序的部分逐个插入前面有序数组中

例如 :
{3,2,1,8,5}
按从小到大顺序排序,先确定3的顺序
{[3],2,1,8,5}
再将2插入前面有序中,则前面的3需要移动位置,排好后即:
{[2],[3],1,8,5}
……
{[1],[2],[3],[5],[8]}

//插入排序
void InsertSort(int A[], int length){
	int temp,i,j;
	for( i = 1;i < length;i++){
		if(A[i]<A[i - 1]){
			temp = A[i]
			for( j = i - 1; A[j] > temp;j--){//和temp比较 
				A[j + 1] = A[j];
			}
			A[j + 1] = temp;//最后一轮j--,所以这里是A[j + 1] 
		}
	}
}

冒泡排序 for-for-if

两两对比交换顺序,每一轮冒出最小/最大的值

例如
{3,2,1,8,5}
冒最大数字:从前往后交换
23185->21385->21358
冒最小数字:从后向前交换
32158->31258->13258

//冒泡排序
void BubbleSort(int A[], int length){
for(int j = 0; j < length ;j++){//控制外循环
	for(int i = length - 1; i > 0;i--){ //一轮排序-内层循环 i>0可以改进为i>j ,减少对比次数
		if(A[i] < A[i-1]){
			int temp = A[i - 1];
			A[i - 1] = A[i];
			A[i] = temp;
			}
		}
	}
}

快速排序 while

快速排序是基于分治算法的
其思想是选择一个待确定参照located(一般是选择待排序的数组的第一位)确定其所在的数组的位置

例如
{3,2 ,1,5,8}
将3作为参照,其排完序的位置应该在第三位

{3,2,1,5,8}
其分为located、low、high
located<=high 不交换 high–
located>=low 不交换 low++
当low=high时 结束

//快速排序
void QuickSort(int A[],int low,int high){
	int i,j,located,t;
	i = low;
	j = high;
	located = A[low];
	
	if(low>high)
		return;
	while(i != j){
		while(i < j && located <= A[j])
			j--;
		while(i < j && located >= A[i])
			i++;
		if(i < j){//内部交换位置
			t = A[i];
			A[i] = A[j];
			A[j] = t;
			}
	}
	A[low] = A[i];//located的确定位置
	A[i] = located;
	QuickSort(A,low,i-1);
	QuickSort(A,i+1,high);
}

选择排序 for-for-if-if

遍历数组,选择最小/最大,然后交换位置

例如
{3,2,1,8,5}
{1,2,3,8,5}>>{1,2,3,5,8}

/******
min作数组下标 A[min]才是最小值
****/
//选择排序
void SelectSort(int A[] ,  int length){
	int min = 0,i,j;
	for( j = 0 ; j < length ; j++){
		min = j;
		for (i = j + 1 ; i < length ; i++){
			if(A[i] < A[min]){
				min = i;
			}
		}
		if(i != min){
			int temp = A[j];
			A[j] = A[min];
			A[min] = temp;
			}
	}
}

归并排序

归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
该算法同样采用分治法,分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之

待排序数组
{[3],[2],[1],[5],[8],[7]}
数组下标 0 1 2 3 4 5
     3 2 1 5 8 7
递归分组
     3 2 1|| 5 8 7
     3 2 || 1 || 5 8 || 7
[3],[2],[1],[5],[8],[7]


其程序思想大概是利用递归将有序数组分组(将问题分解成逐个小问题),再执行归并操作(解决小问题)

程序执行过程:
第一次归并
{1,2} {3} {5,7} {8}
第二次归并
{1,2,3} {5,7,8}
第三次归并
{1,2,3,5,7,8}

归并的过程可看成一颗二叉树,可通过探讨二叉树来分析算法的复杂度

//归并排序
void Merge(int A[],int low,int high){
	int *B = (*int)malloc((high - low + 1)*sizeof(int));
	int mid = (low + high)/2;
	int i = low;
	int j = mid + 1;
	int k = 0;
	for(k = low;k <= high ; k++){
		B[k] = A [k];
	}
	for(k = i; i <= mid && j <= high;k++){
		if(B[i] <= B[j]){
			A[k] = B[i++];
		} 
		else
			A[k] = B[j++];
	}
	while(i <= mid)		A[k++] = B[i++];
	while(j <= high)	A[k++] = B[j++];	
	free(B);
}

void MergeSort(int A[],int low,int high){
	if(low < high){
		int mid = (low + high)/2;
		MergeSort(A,low,mid);
		MergeSort(A,mid + 1,high);
		Merge(A,low,high);
		}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值