C语言八大排序


sort.h

c 复制代码
#define SWAP(x,y) {int tmp = x; x = y; y = tmp;}
#define N 20000000
#define M 100
void print(int *arr);
void bubbleSort(int *arr);
void selectSort(int *arr);
void insertSort(int *arr);
void shellSort(int *arr);
void quickSort(int *arr, int left, int right);
int partition(int *arr, int left, int right);
int myCompare(const void* p1, const void *p2);
void adjustMaxHeap(int *arr, int pos, int len);
void heapSort(int *arr);
void merge(int *arr, int *brr, int left, int mid, int right);
void mergeSort(int *arr, int *brr, int left, int right);
void countSort(int *arr);

main.c

c 复制代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "sort.h"
int main() {
	/*int a = 10, b = 5;
	SWAP(a, b);
	printf("a = %d, b = %d\n", a, b);*/
	srand((unsigned int)time(NULL));
	//int arr[N];
	int *arr = (int *)malloc(N * sizeof(int));
    //brr是用于归并排序的额外申请的空间
	int *brr = (int *)malloc(N * sizeof(int));
	for (int i = 0; i < N; ++i) {
		arr[i] = rand() % M;
	}
	//print(arr);
    //bubbleSort(arr);
	//selectSort(arr);
	//insertSort(arr);
	time_t begTime = time(NULL);
	//shellSort(arr);
	//selectSort(arr);
	//quickSort(arr, 0, N - 1);
    //qsort(arr, N, sizeof(int), myCompare);  //qsort函数的使用,非递归版本的快速排序
	//heapSort(arr);
	mergeSort(arr, brr, 0, N - 1);
	time_t endTime = time(NULL);
	printf("Total time = %lld s\n", endTime - begTime);
	//partition(arr, 0, N - 1);
	//print(arr);
	
}
void print(int *arr) {
	for (int i = 0; i < N; ++i) {
		printf("%3d", arr[i]);
	}
	printf("\n");
}
//0 冒泡排序
void bubbleSort(int *arr) {
    for (int i = N-1; i > 0; --i) {
        for (int j = 0; j < i; ++j) {
            if(arr[j] > arr[j + 1]) {
                SWAP(arr[j], arr[j + 1]);
            }
        }
    }
}
//1 选择排序
void selectSort(int *arr) {
	for (int i = 0; i < N - 1; ++i) {
		//i 最小值将要放入的下标
		//待比较的数据的下标范围 i ~ N-1
		int minPos = i; //存储最小值的下标
		for (int j = i + 1; j < N; ++j) {
			// j 待比较的数据的下标
			if (arr[minPos] > arr[j]) {
				minPos = j;//更新minPos
			}
		}
		SWAP(arr[i], arr[minPos]);
	}
}
//2 插入排序
void insertSort(int *arr) {
	for (int i = 1; i < N; ++i) {
		//i表示来牌的下标
		int insertVal = arr[i];//复制一份来牌
		int j;//表示探查的手牌下标 比较之后牌要拷贝到j+1的位置
		for (j = i - 1; j >= 0 && arr[j] > insertVal; --j) {
			arr[j + 1] = arr[j];
		}//退出循环时,j = -1 或者 arr[j] < insertVal
		arr[j + 1] = insertVal;
	}
}
//3 希尔排序
void shellSort(int *arr) {
	for (int d = N / 2; d >= 1; d >>= 1) {
		for (int i = d; i < N; ++i) {
			int insertVal = arr[i];
			int j;
			for (j = i - d; j >= 0 && arr[j] > insertVal; j -= d) {
				arr[j + d] = arr[j];
			}
			arr[j + d] = insertVal;
		}
	}
}
//4 快速排序,分而治之思想,递归 
void quickSort(int *arr, int left, int right) {
	if (left < right) {//数组中至少2个元素
		int pivot = partition(arr, left, right);
		quickSort(arr, left, pivot - 1);
		quickSort(arr, pivot + 1, right);
	}
}
int partition(int *arr, int left, int right) {
    //i用来遍历,j表示比arr[right]大的那部分数据的最左端边界
	int i, j;
	for (i = left, j = left; i < right; ++i) {
		if (arr[i] < arr[right]) {
			SWAP(arr[i], arr[j]);
			++j;
		}
	}
	SWAP(arr[j], arr[right]);
	return j;
}
//qsort中的回调函数实现
int myCompare(const void* p1, const void *p2) {
	int *pleft = (int *)p1;
	int *pright = (int *)p2;
	return *pleft - *pright;
}
//调整堆
void adjustMaxHeap(int *arr, int pos, int len) {
	//pos 调整的起点的下标 李渊的下标 编号pos+1 
	//左孩子编号2*pos+2 左孩子下标2*pos+1 右孩子下标 = 左孩子下标+1
	//len 当前堆的规模 
    //最后一个结点的下标len-1
	int dad = pos;
	int son = 2 * pos + 1;
	while (son < len) {
		//如果son在堆内
		// 1 兄弟阋墙
		if (son + 1 < len && arr[son] < arr[son + 1]) {
			++son;//右孩子存在且比左孩子强
		}
		// 2 父子反目
		if (arr[son] > arr[dad]) {
			SWAP(arr[son], arr[dad]);
			dad = son;
			son = 2 * dad + 1; // 李渊坐在原来李世民的位置,接受手下的挑战
		}
		else {
			break;//李渊的位置坐稳了
		}
	}
}
//5 堆排序
//整体步骤:1、对无序数据进行建堆操作 2、循环执行,交换堆顶和末尾,重新调整成大根堆,缩小堆的规模,重新建堆
void heapSort(int *arr) {
	//最后一个结点的编号是N 父亲的编号是N/2 下标是N/2-1
	for (int i = N / 2 - 1; i >= 0; --i) {
		//i表示父结点的下标
		adjustMaxHeap(arr, i, N);
	}//这个循环的目的从无序元素中建立大根堆
	SWAP(arr[0], arr[N - 1]);
	for (int i = N - 1; i >= 2; --i) {
		//i表示堆的规模
		adjustMaxHeap(arr, 0, i);//交换之后,从根出发调整堆
		SWAP(arr[0], arr[i - 1]);//交换堆顶和末尾
	}
}
//归并排序的合并操作
void merge(int *arr, int *brr, int left, int mid, int right) {
	//把原来的数据从arr拷贝到brr
	memcpy(brr + left, arr + left, (right - left + 1) * sizeof(int));
	int i, j, k;
	//i 用遍历左半边 j用来遍历右半边 k指向结果
	for (i = left, j = mid + 1, k = left; i <= mid && j <= right; ++k) {
		if (brr[i] < brr[j]) {
			arr[k] = brr[i];
			++i;
		}
		else {
			arr[k] = brr[j];
			++j;
		}
	}
	while (i <= mid) {//右半边放完了
		arr[k] = brr[i];
		++i;
		++k;
	}
	while (j <= right) {//左半边放完了
		arr[k] = brr[j];
		++j;
		++k;
	}
}
//6 归并排序
void mergeSort(int *arr, int *brr, int left, int right) {
	if (left < right) {//至少有两个元素
		int mid = (left + right) / 2;
		mergeSort(arr, brr, left, mid);//排序左半边
		mergeSort(arr, brr, mid + 1, right);//排序右半边
		merge(arr, brr, left, mid, right);//合并有序的左右两个半边
	}
}
//7 计数排序
void countSort(int *arr) {
    //创建一个计数的数组
    int count[M] = {0};
    for (int i = 0; i < N; ++i) {
        ++count[arr[i]];
    }
    for (int i = 0, j = 0; i < M; ++i) {
        //i表示count数组的下标
        //j表示重建之后arr数组的下标
        for (int k = 0; k < count[i]; ++k) {
            //k用来根据count[i]的值,控制写回的次数
            arr[j] = i;
            ++j;
        }
    }
}
相关推荐
sp_fyf_202410 分钟前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸31 分钟前
链表的归并排序
数据结构·算法·链表
jrrz082831 分钟前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time42 分钟前
golang学习2
算法
南宫生2 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步2 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
DARLING Zero two♡2 小时前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
Ni-Guvara3 小时前
函数对象笔记
c++·算法
泉崎3 小时前
11.7比赛总结
数据结构·算法
你好helloworld3 小时前
滑动窗口最大值
数据结构·算法·leetcode