排序C语言版

  • Post author:
  • Post category:其他


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

//一下排序方法默认从小到大,数组从0开始

/**
 * 直接插入排序:边比较边移动位置
 *  
 * */

void directSort(int *a, int length){
	int i,j; 
	for(i = 1; i < length;i++){//i 从1开始知道数组结尾
		if(a[i-1] > a[i]){
			//开始寻找位置
			int tmp = a[i];
			for(j=i-1; j >= 0;j--){
				if(a[j] > tmp){
					a[j+1] = a[j];//向后移动位置
				}else{
					break;
				}
			}
			a[j+1] = tmp;//赋值
		}
	}
}

/**
 * 折半插入排序:先找位置在移动元素
 * 
 * 
 * */
void binarySort(int *a, int length){
	int i,low,height,mid;
	for(i = 1; i < length ;i++){//和直接插入排序一样从1开始
		//寻找需要插入的位置
		int tmp = a[i];
		low = 0; height = i-1;
		while (low <= height){
			mid = (low + height)/2;
			if(a[mid] < tmp){
				low = mid+1;
			}else{
				height = mid -1;
			}
		}
		//移动height后面的元素
		for(int j = i-1; j >= height; j--){
			a[j+1] = a[j];
		}
		a[height+1] = tmp;//赋值
	}
}


/**
 * 希尔排序:先基本有序在整体有序
 * 根据步长来排
 * 
 * */
void shellSort(int *a, int length){
	int dk,i,j;//dk步长,i 比较时用,j 寻找插入位置时用 
	for(int dk = length/2; dk > 0; dk /= 2){ //步长从length/2 到 1
		for(i = dk ;i < length; i++){ //i 从第二个分组到最后
			if(a[i] < a[i-dk]){
				int tmp = a[i];//tmp是哨兵
				for(j = i-dk; j >= 0 && tmp < a[j];j -= dk){
					a[j+dk] = a[j];
				}
				a[j+dk] = tmp;
			}
			
		}
		// printf("dk = %d,i = %d \n",dk,i);
		// for (int k = 0; k < length ; k++){
		// 	printf("%d ", a[k]);
		// }
		// printf("\n");
	}
}

/**
 * 冒泡排序:一层一层的向外冒
 * 
 * */
void bubbleSort(int *a, int length){
	bool flag = false;
	//每次循环都找出最小的一个放在第i位
	for(int i = 0 ;i < length; i++){
		//循环比较找出最小的一个来
		for(int j = length-1;j >i ;j--){
			if(a[j] < a[j-1]){
				int tmp = a[j];a[j] = a[j-1];a[j-1] =tmp;
				flag =true;
			}
		}
		// for (int k = 0; k < length ; k++){
		// 	printf("%d ", a[k]);
		// }
		// printf("\n");
		if(!flag){
			return;
		}
		
	}
}

/**
 * 快速排序:每次选一个数作为基准,每进行一次划分就会将基准放到它最终的位置
 * 
 * */
//进行划分
int partition(int *a,int low, int height){
	//存放基准
	int tmp = a[low];
	//寻找tmp的最终位置,直到low == height时结束
	while(low < height){
		//从height往后找,找到一个比基准小的数据
		while (low < height && tmp <= a[height]){
			height--;
		}
		a[low] =a[height];
		//从low往前找找到一个比基准大的数据
		while (low < height && tmp >= a[low]){
			low++;
		}
		a[height] = a[low];
	}
	a[low] = tmp;
	return low;
}
//定义一个递归
void quickSort(int *a,int low, int height){
	if(low < height){
		int i = partition(a,low,height);
		//利用了二叉查找的思想
		quickSort(a,low,i-1);
		quickSort(a,i+1,height);
	}
}

/**
 * 简单选择排序:每次选一个最小的元素放在第i个位置
 * 
 * */
void selectSort(int *a, int length){
	//遍历整个数组除了最后一位
	for(int i = 0;i < length - 1; i++){
		int min = i;
		for(int j = i+1;j < length ; j++){//寻找最小的位置
			if(a[min] > a[j]){
				min = j;
			}
		}
		//交换
		if(min != i){
			int tmp = a[min];
			a[min] = a[i];
			a[i] = tmp;			
		}
	}
}
/**
 * 堆排序:利用大根堆或者小根堆的性质
 * 数组下标从0开始,这里传入的值是数组的长度
 * */

//这个方法是重点
void headAndJust(int *a,int k ,int length){
	//暂存根节点
	int tmp = a[k];
	//i为k 的左孩子,每次循环之后k都是根、左、右中最大的节点
	for(int i = 2*k+1;i < length;i = i*2+1){
		//选取孩子较大的节点,若右孩子比较大,则令i++
		if(i  < length-1 && a[i] < a[i+1]){
			i++;
		}
		if(tmp >= a[i]){//左孩子大于右孩子,但是小于根节点
			break;
		}else{//左孩子大于右孩子,且大于根
			a[k] = a[i];//将a[i]调整到双亲节点上
			k = i;
		}
	}
	//将根节点放到相应的位置上
	a[k] = tmp;
}

//初始化堆
void buildMaxHeap(int *a,int length){
	//从最后一个分支节点开始向前遍历
	for(int i = length/2;i >= 0;i--)
		headAndJust(a,i,length);

	for (int t = 0; t < length; t++)
	{
		printf("%d ", a[t]);
	}
	printf("\n");
}

//堆排序
void heapSort(int *a,int length){
	buildMaxHeap(a,length);
	for(int i = length-1;i > 0 ; i--){
		//没有排好序的交换第一个元素和最后一个元素
		int tmp = a[0];
		a[0] = a[i];
		a[i] = tmp;
		//进行堆的调整由0到i
		headAndJust(a,0,i);
	}
}

/**
 * 归并排序:将两个有序的序列合并为一个有序队列
 * 二路归并排序用于内部排序,多路归并排序用于外部排序
 * 
 * 重点是merge()
 * */

void merge(int *a,int low,int mid, int high){
	int i ,j,k;
	//需要一个辅助空间,暂时存贮需要合并的两个子序列
	int *b = (int*)malloc(sizeof(a));
	//将需要排序的两个子序列复制到b
	for(int i = low;i <= high;i++){
		b[i] = a[i]; 
	}
	//循环比较两个子序列,插入到a中,直到有一个子序列为空
	for(i = low,j = mid+1,k = i; i <= mid && j <= high;k++){
		if(b[i] <= b[j]){
			a[k] = b[i];
			i++;
		}else{
			a[k] = b[j];
			j++;
		}
	}
	//若有一个子序列还没有完则直接加到末尾
	while (i <= mid){
		a[k++] = b[i++];
	}
	while (j <= high){
		a[k++] = b[j++];
	}

}

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,mid,high);//归并
	}

}


int main(){
	int t;
	// int array[] = {50, 26, 38, 80, 70, 90, 8, 30, 40, 20};

	int array[] = {53, 17, 78, 9, 45, 65, 87, 32};
	// heapSort(array , sizeof(array) / sizeof(array[0]));

	mergeSort(array , 0 ,(sizeof(array) / sizeof(array[0]))-1);

	for (t = 0; t < sizeof(array) / sizeof(array[0]); t++)
	{
		printf("%d ", array[t]);
	}
	printf("\n");
	return 0;
}




版权声明:本文为qq_40981804原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。