学习笔记:五种基础排序C语言实现

五种基础排序-升序实现

插入排序

构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。


void InsertSort(int buf[], int bufsize)
{
    for (int i = 1; i < bufsize; i++){
        int temp = buf[i];
        int j = i - 1;
        // 只移动,不插入
        while (j >= 0 && buf[j] > temp){
            buf[j + 1] = buf[j];
            j--;
        }
        // 统一插入:位置是 j+1
        buf[j + 1] = temp;
    }
}

冒泡排序

重复地走访要排序的数列,依次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复进行直到没有再需要交换,然后排序完成

void BubbleSort(int buf[], int bufsize)
{
	int Temp = 0;
	//i从1开始,表示第一轮比较
	for(int i=1;i<bufsize;i++){
		//每轮比较完都会找到一个最大的数放在数组最后,下轮需要参与比较的数减低1
		for (int j=0;j<bufsize-i;++j){

			if(buf[j]>buf[j+1]){
				Temp = buf[j];
				buf[j] = buf[j+1];
				buf[j+1] = Temp;
			}
		}
	}
}

选择排序

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。直到所有元素均排序完毕。

void SelectSort(int buf[], int bufsize)
{
    //// 当只剩一个元素时,没比较对象,自身就是最小的,所以 n < bufsize - 1,无需再比较
    for (int n = 0; n < bufsize - 1; n++) {
        int index = n;// 假设当前无序部分的第一个元素(下标 n)是最小的
                        // index 用于记录当前找到的最小元素的下标
        for (int m = n + 1; m < bufsize; m++) {
            // 如果发现比 buf[index] 更小的元素
            if (buf[m] < buf[index]) {
                index = m;
            }
        }
        // 使用临时变量安全交换
        if (index != n) {  // 避免不必要的交换
            int temp = buf[n];
            buf[n] = buf[index];
            buf[index] = temp;
        }
    }
}

快速排序

把一个序列分为较小和较大的两个子序列,然后递归地排序两个子序列。具体过程是选择一个“基准”元素,将数组划分为比基准小的元素和比基准大的元素两部分,再对这两部分分别递归进行快速排序。

// buf[]: 待排序的数组
// low:  当前排序区间的起始下标
// high: 当前排序区间的结束下标
void QuickSort(int buf[],int low,int high)
{	
	int l=low,h=high;
	int temp;
	// 递归终止条件:如果区间无效(low >= high),直接返回
	if(low<high)
	{
		temp=buf[low];// 选择第一个元素作为“基准值”
		while(l!=h)
		{
			// 步骤1:从右往左找,跳过比基准大的元素
            // 直到找到一个小于等于基准的元素,准备“填坑”
			while(l<h&&buf[h]>temp)h--;
			if(l<h)
			{
				buf[l]= buf[h];
				++l;
			}
			// 步骤2:从左往右找,跳过比基准小的元素
            // 直到找到一个大于等于基准的元素,准备“填坑”
			while(l<h&&buf[l]<temp)l++;
			if(l<h)
			{
				buf[h]=buf[l];
				--h;
			}
			// 如此反复,左右交替“填坑”,直到 l == h
		}
		buf[l] = temp;
		// 此时,基准左边都小于它,右边都大于它
        // 递归对左右两个子区间进行快速排序
		QuickSort(buf,low,l-1);
		QuickSort(buf,l+1,high);
	}
}

计数排序

计数排序不是基于比较的排序算法,它的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。(该版本不适合有重复元素的稳定排序,且输出到B数组)

void CountSort(int A[],int B[],int size)
{
	int cnt;//用于统计A[]中比A[i]小的元素个数
	for(int i = 0;i < size;i++)
	{
		cnt = 0;
		for(int j=0;j<size;j++)
		{
			if(A[j]<A[i]){
				cnt++;
			}
		}
        //A[]中比A[i]小的元素个数为cnt个,A[i]值就放到B[cnt]
		B[cnt]=A[i];
	}
}


测试

#include <stdio.h>

/**
	五种排序函数定义
*/

// 打印数组
void PrintArray(int arr[], int size) {
    for (int i = 0; i < size; ++i) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main(int argc, char const *argv[])
{
	int arr[] = {14, 23, 12, 5, 8, 3, 9, 10, 33, 6};
    int size = sizeof(arr) / sizeof(arr[0]);

    printf("原始数组: ");
    PrintArray(arr, size);

    // 测试 InsertSort
    int arr1[size];
    for (int i = 0; i < size; i++) arr1[i] = arr[i];
    InsertSort(arr1, size);
    printf("插入排序后: ");
    PrintArray(arr1, size);

    // 测试 BubbleSort
    int arr2[size];
    for (int i = 0; i < size; i++) arr2[i] = arr[i];
    BubbleSort(arr2, size);
    printf("冒泡排序后: ");
    PrintArray(arr2, size);

    // 测试 SelectSort
    int arr3[size];
    for (int i = 0; i < size; i++) arr3[i] = arr[i];
    SelectSort(arr3, size);
    printf("选择排序后: ");
    PrintArray(arr3, size);

    // 测试 QuickSort
    int arr4[size];
    for (int i = 0; i < size; i++) arr4[i] = arr[i];
    QuickSort(arr4, 0, size - 1);
    printf("快速排序后: ");
    PrintArray(arr4, size);

    // 测试 CountSort
    int arr5[size];  // 输出数组
    CountSort(arr, arr5, size);
    printf("计数排序后: ");
    PrintArray(arr5, size);

    return 0;
}

测试结果

vmware_zLACP7zmGV

posted @ 2025-08-05 13:16  Yue+  阅读(91)  评论(0)    收藏  举报