排序算法合集1.0

目录 

冒泡排序(Bubble sorting)

选择排序(Select sort)

插入排序(Insert sort)

希尔排序(Shell Sort)

快速排序(Quick sort)

归并排序(Merge sort)

基数排序(Radix Sort)


冒泡排序(Bubble sorting)

冒泡排序算法的原理如下: 

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 

  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

冒泡排序算法时间复杂度:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 200

int bubbleSort(int* arr, int num){
	int temp;  //定义临时遍历
	int flag = 0;  //定义标记 
	int i, j;
	
	for(i = 0; i < num - 1; i++){
		for(j = 0; j < num - 1 - i; j++){
			if(arr[j] > arr[j + 1]){
				flag = 1;
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
		if(!flag){  //如果flag = 0,那么说明这一趟没有进行交换数据,则说明已经有序了 
			return 1;
		}else{  //如果交换了数据,那么要把flag重新置为0,方便下一轮标记 
			flag = 0;
		}
	} 
} 

int comp(const void*a,const void*b)//用来做比较的函数。
{
    return *(int*)a-*(int*)b;
}

int main(int argc, char *argv[]) {
	int num;  //定义需要输入的数据的个数
	int arr[N];  //定义一维数组
	int i;
	time_t t;
	
	scanf("%d", &num);
	
	for(i = 0; i < num; i++){
		scanf("%d", &arr[i]);
	} 
	
	bubbleSort(arr, num);
//	qsort(arr, num, sizeof(int), comp); //测试qsort 
	
	for(i = 0; i < num; i++){
		printf("%d ", arr[i]);  //打印已经排序好的数组 
	}
	
	return 0;
}

选择排序(Select sort)

选择排序算法的原理如下:

        第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

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

#define N 200

//选择排序 
void selectSort(int* arr, int num){
	int i, j;
	int min, minIndex;  //min表示最小的元素,minIndex表示最小元素的下标 
	
	for(i = 0; i < num - 1; i++){
		min = arr[i];
		minIndex = i;
		for(j =i ; j < num; j++){
			if(min > arr[j]){  //从小到大排序,若要从大到小排序则改为< 
				min = arr[j];
				minIndex = j;
			}
		} 
		if(minIndex != i){  //数组后面存在元素比当前元素小的元素时才交换
			arr[minIndex] = arr[i];  //更小元素的元素位置换为当前元素 
			arr[i] = min;   //当前元素换位更小元素 
		}
	}
}

int main(int argc, char *argv[]) {
	int num;
	int arr[N];
	int i;
	
	scanf("%d", &num);
	
	for(i = 0; i < num; i++){
		scanf("%d", &arr[i]);
	} 
	
	selectSort(arr, num);
	
	printf("选择排序后的结果为:\n");
	for(i = 0; i < num; i++){
		printf("%d ",arr[i]);
	} 
	return 0;
}

插入排序(Insert sort)

插入排序算法的原理如下:

        插入排序是指在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序 。

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

#define N 200

// 插入排序
void InsertSort(int* arr, int num){
	int insertVal, insertIndex;
	int i;
	
	for(i = 1; i < num; i++){
		insertVal = arr[i];  //将待插入的元素赋值给insertVal
		insertIndex = i - 1;  //将待插入的元素下标赋值给insertIndex
		while(insertIndex >= 0 && insertVal < arr[insertIndex]) {  //从后向前比较,若待插入元素比前面的元素小,则执行以下操作 
			arr[insertIndex + 1] = arr[insertIndex];  //比待插入元素大的元素后移
			insertIndex--;  //insertIndex - 1,待插入位置向前移一个位置,比较前一个元素 
		}
		if((insertIndex + 1) != i){  //判断待插入位置与原始位置是否一样,若不同则插入 
			arr[insertIndex + 1] = insertVal;  
		} 
	}
} 

int main(int argc, char *argv[]) {
	int num;
	int arr[N];
	int i;
	
	scanf("%d", &num);
	for(i = 0; i < num; i++){
		scanf("%d", &arr[i]);
	}
	
	InsertSort(arr, num);
	
	printf("排序好的数组如下:\n");
	for(i = 0; i < num; i++){
		printf("%d ", arr[i]);
	}
	return 0;
}

希尔排序(Shell Sort)

希尔排序算法的原理如下:

        希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。

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

#define N 200

//交换法希尔排序
void shellSort(int *arr, int num){
	int gap, i, j;
	int temp;
	
	//gap是步长,希尔排序每轮分组进行比较交换的数据间隔gap 
	for(gap = num / 2; gap > 0; gap /= 2){
		//当没有比较到最后一组时,继续执行 
		for(i = gap; i < num; i++){
			//计算同一组的成员有谁 
			for(j = i - gap; j >= 0; j -= gap){
				//如果前面的元素比后面的元素大,则交换两个数据 
				if(arr[j] > arr[j + gap]){
					temp = arr[j];
					arr[j] = arr[j + gap];
					arr[j + gap] = temp;
				}
			}
		} 
	}
} 

//移位法希尔排序
void shellSort2(int *arr, int num){
	int gap, temp, i, j;
	
	for(gap = num / 2; gap > 0; gap /= 2){
		for(i = gap; i < num; i++){
			j = i;
			temp = arr[i];
			if(arr[j] < arr[j - gap]){
				//temp比前面的元素小时,就将前面的元素后移 
				while(j - gap >= 0 && temp < arr[j - gap]){
					arr[j] = arr[j - gap];
					j -= gap;
				}
				//推出while循环,即找到合适的位置
				arr[j] = temp; 
			}
		}
	}
} 
int main(int argc, char *argv[]) {
	int num, i;
	int arr[N];
	
	scanf("%d", &num);
	
	for(i = 0; i < num; i++)
		scanf("%d", &arr[i]);
	
	//shellSort(arr, num);
	shellSort2(arr, num);
	
	//希尔排序排好后的结果
	printf("希尔排序后的结果:\n"); 
	for(i = 0; i < num; i++){
			printf("%d ",arr[i]);
	}
	return 0;
}

快速排序(Quick sort)

1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;

2)以第一个数组元素作为关键数据,赋值给key,即key=A[0]; 

3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]的值交换;

4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换; 

5)重复第3、4步,直到i==j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

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

#define N 200

int getIndex(int* arr, int left, int right){
	//基准数据 
	int temp = arr[left];
	while(left < right){
		//当右边数据大于等于基准数据时,向前移动right指针 
		while(left < right && arr[right] >= temp){
			right--;
		}
		//如果找到比基准数据小的,将其赋值给arr[left] 
		arr[left] = arr[right];
		//当左边数据小于等于基准数据时,向后移动left指针 
		while(left < right && arr[left] <= temp){
			left++;
		}
		//如果找到比基准数据大的,将其赋值给arr[right] 
		arr[right] = arr[left];
	}
	//while循环结束后,left == right
	//此时,找到基准数据在该数组中的正确位置
	//比基准数据大的元素都在基准数据右边 ,比基准数据小的元素都在基准数据左边 
	//将正确位置赋值上基准数据 
	arr[left] = temp;
	//返回基准数据的正确位置,对左边、右边进行快速排序 
	return left;
}

void quickSort(int *arr, int left, int right){
	int index;
	if(left < right){
		//找基准数据的正确位置 
		index = getIndex(arr, left, right);
		
		//向左递归 
		quickSort(arr, left, index - 1);
		//向右递归 
		quickSort(arr, index + 1, right);
	}
}

int main(int argc, char *argv[]) {
	int num;
	int arr[N];
	int i;
	
	scanf("%d", &num);
	
	for(i = 0; i < num; i++){
		scanf("%d", &arr[i]);
	}
	
	quickSort(arr, 0, num - 1);
	
	printf("快速排序后数组为:\n");
	for(i = 0; i < num; i++){
		printf("%d ", arr[i]);
	} 
	
	return 0;
}

归并排序(Merge sort)

第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置

第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

重复步骤3直到某一指针超出序列尾

将另一序列剩下的所有元素直接复制到合并序列尾

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

//合并的方法
//arr:待排序数组,left:左边初始索引;mid:中间索引;right:右边索引;temp:临时数组 
void merge(int *arr, int left, int mid, int right, int *temp){
	//left和right是边界,i和j是索引 
	int i = left, j = mid + 1, t = 0, tempLeft = left;  //t是temp数组的索引, tempLeft是后面复制temp是需要的 
	
	//(一) 将两边的数组中较小的元素放入temp
	while(i <= mid && j <= right){
		if(arr[i] <= arr[j]){
			temp[t] = arr[i];  //把较小的arr[i]赋值给temp
			t++;
			i++; 
		}else{
			temp[t] = arr[j];
			t++;
			j++;
		}
	} 
	
	//(二) 将左(或右)边没有放完的数据放到temp中
	while(i <= mid){
		temp[t] = arr[i];
		t++;
		i++;
	} 
	while(j <= right){
		temp[t] = arr[j];
		t++;
		j++;
	}
	
	//(三) 把temp复制到arr,因为每次不一定是从0复制到7,所以设置tempLeft和t 
	for(t = 0, tempLeft = left; tempLeft <= right; t++, tempLeft++){
		arr[tempLeft] = temp[t];
	}
}  

//分+合
void mergeSort(int *arr, int left, int right, int *temp){
	int mid = (left + right) / 2;
	//left == right是递归出口 
	if(left < right){
		//分
		mergeSort(arr, left, mid, temp);
		mergeSort(arr, mid + 1, right, temp);
		//合
		merge(arr, left, mid, right, temp);
	}
	
} 

int main(int argc, char *argv[]) {
	int num, i;
	int *arr, *temp;
	
	scanf("%d", &num);
	
	arr = (int *)malloc(sizeof(int) * num);
	temp = (int *)malloc(sizeof(int) * num);
	
	for(i = 0; i < num; i++){
		scanf("%d", &arr[i]);
	}
	
	mergeSort(arr, 0, num - 1, temp);
	
	printf("归并排序后的数组是:\n");
	
	for(i = 0; i < num; i++){
		printf("%d ", arr[i]);
	} 
	
	free(temp);
	free(arr); 
	
	return 0;
}

基数排序 / 桶排序(Radix Sort)

将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

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

//基数(桶)排序
void radixSort(int* arr, int num){
	//记录最大数组中最大的元素 和 最大数的位数 
	int max, maxLength = 0;
	int i, j, n, k, index = 0;  //循环变量 
	int digitOfElement; //每个元素相应位数的值 
	//定义一个二维数组,表示10个桶,每个桶就是一个一维数组
	//说明:
	//(1)二维数组包含10个一维数组 分别表示位数对应 0,1,2,3,4,5,6,7,8,9 
	//(2)为了防止在放入元素的时候数据溢出,每个一维数组(桶),大小定义为num
	//(3)基数排序是使用空间换时间的经典算法 
	int bucket[10][num]; 
	//为了记录每个桶中实际放了多少个数据,定义一个一维数组记录各个桶每次放入数据的个数 
	//bucketElementCounts[i] 分别表示位数对应 0,1,2,3,4,5,6,7,8,9  
	int bucketElementCounts[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
	
	//找到数组中最大数的位数
	max = arr[0];  //基准数据 
	for(i = 1; i < num; i++){
		if(arr[i] > max){
			max = arr[i];
		}
	}
	//得到最大数的位数
	do{
		maxLength++;
		max /= 10;
	}while(max != 0); 
	
	//基数排序 
	//进行最大位数次排序 
	for(i = 0, n = 1; i < maxLength; i++, n *= 10){

		for(j = 0; j < num; j++){
			//取出每个元素相应位数的值
			digitOfElement = arr[j] / n % 10;
			//放入桶中
			bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j]; 
			bucketElementCounts[digitOfElement]++;
		} 
		index = 0;
		//按照桶的顺序(一维数组下标)把元素取出,放回原来的数组
		//遍历每一个 桶,并将桶中的数据放入原数组 
		for(j = 0; j < 10; j++){
			//如果桶中有数据,我们才放入
			if(bucketElementCounts[j]){
				//循环第j个桶
				for(k = 0; k < bucketElementCounts[j]; k++){
					//取出元素,index作为循环变量 
					arr[index++] = bucket[j][k]; 
				} 
			}
			//!每一轮处理完后,要把bucketElementCounts[j] = 0
			bucketElementCounts[j] = 0;
		}

	}
} 


int main(int argc, char *argv[]) {
	int num, i;
	int *arr;
	
	scanf("%d", &num);
	arr = (int *)malloc(sizeof(int) * num);
	
	for(i = 0; i < num; i++){
		scanf("%d", &arr[i]);
	}
	
	radixSort(arr, num);
	
	printf("基数排序后的结果如下:\n");
	for(i = 0; i < num; i++){
		printf("%d ", arr[i]);
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值