目录
冒泡排序(Bubble sorting)
冒泡排序算法的原理如下:
-
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
-
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
-
针对所有的元素重复以上的步骤,除了最后一个。
-
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
冒泡排序算法时间复杂度:
#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;
}