C语言程序设计之二分法(快速)排序

        二分法也叫快速排序法,是算法中几种排序思想最为复杂的一种,它的思想是在一组数据中找一个基准值,然后把所有大于这个基准值的数都放在这个基准值的右边,所有小于这个基准值的数都放在这个基准值的左边。然后将这个数据分成了两个小的数组,再从这两个小的数组中分别找一个基准值,对这两个小的数组再进行精分,依次类推,用到了函数中递归的思想,其整体思想与折半查找法也十分相似。

#include<stdio.h>
int main(){
    int quick_sort(int Arr[],int low,int hight);
    int arr[10];

    //为数组赋值
    printf("Please input ten numbers.\n");
    for(int i=0;i<10;i++){
        scanf("%d",&arr[i]);
    }

    //将数组的所有元素打印一遍
    for(int i=0;i<10;i++){
        printf("%d ",arr[i]);
    }

    printf("\n");      //换行

    int len = sizeof(arr)/sizeof(int);   //定义一个变量len用来存储数组的长度

    //为数组排序
    quick_sort(arr,0,len);

    //输出排序后的数组
    for(int i=0;i<10;i++){
        printf("%d ",arr[i]);
    }
    return 0;
}

int quick_sort(int *arr,int low,int hight){     /*定义一个函数quick_sort,它的形参分别是一个指针arr(指向数组arr),一个整型变量low
                                                (就是数组最左边的元素),一个整型变量hight(就是数组最右边的元素)*/
    int left = low;     //定义一个整型变量left来存储形参low的值
    int right = hight;  //定义一个整型变量hight来存储形参hight的值
    int key = arr[left];    //定义一个整型变量key,用来存储数组的第一个元素作为基准值。
    while (left<right)      //这个循环是用来进行推进排序
    {
        while (left<right && arr[right]>=key)   /*可以想象一下有一个向上的箭头这个时候指向的这个数组最右边的数,即下标为9的数,当left<right的时候
                                                也就是当数组下标从右边自减,只要不等于0,该表达式就成立,同时要满足arr[right]>=key,就是当right自减
                                                一次这个箭头就朝左挪一个位置,那么只要这个这个箭头指向的数组元素不小于基准值(arr[0])那么就继续往下走*/
        {
            right--;    //跳出循环的条件同时也是使循环继续的条件。
        }
        arr[left] = arr[right];     /*当上面循环的条件不满足时跳出了循环,那么不满足循环的条件有两个,一个是left=right,也就是说这个数组arr[0]右边的
                                    所有数都比基准值key(arr[0])大,另一个是arr[right]<key,也就是说在循环的中途遇到了一个数arr[right]它的值要比
                                    基准值key(arr[0])小。那么这个时候我们让左边的值等于右边的值,也就是说arr[0]等于了它自己或者等于了那个小于基准值的
                                    arr[right]*/

        while (left<right && arr[left]<=key)    /*完成了上面的循环我们找到了第一个小于或者等于基准值的元素,并将它赋值给了arr[0],(这里要将基准值与arr[0]
                                                区别开来,因为虽然arr[0]的值变了,但是基准值key的值还是我们之前的arr[0]的值),下面这个循环就是来找一个大于
                                                基准值的数,原理同上。想象有一个朝上的箭头此时指向的是最左边的数组元素,当left<right时(要知道的是right
                                                在上面进行了自减操作,因此right此时的值并不是9,而是上面那个小于基准值的元素的下标)同时要满足arr[left]<=key
                                                也就是要满足左边的元素值小于或者等于基准值key(这个基准值还是原本的arr[0]),当这个两个条件都满足时使left自减
                                                也就是让这个箭头向右移指向下一个数组元素*/
        {
            left++;     //跳出循环的条件同时也是推进循环的条件
        }
        arr[right] = arr[left];     /*和上面一样,当循环被终止的时候有两个原因,一个是left=right,这就说明左边的所有元素值都小于等于基准值key(原本的arr[0])
                                    另一个原因是arr[left]>key,也就是说在循环的途中遇到了一个左边的元素值大于基准值key的数,那么我们这个时候就让
                                    arr[right] = arr[left]也就是把这个大于或者等于基准值的值放到基准值的右边*/
    }
    arr[left] = key;    /*大循环结束的条件是left=righ或者left>right,也就是left的自增和right的自减使循环结束了,那么这个时候我们使arr[left] = key,也就是
                        将基准值(最初的arr[0])的值赋给arr[left],这个时候的arr[left]实际上就是这个组数据中的一个中间位置的数,因为在所有的元素值的顺序都排完
                        以后我们的最中间的下标为4和下标为5的元素的值相等了,这是因为我们前边不断的左边赋给右边右边赋给左边致使最初的基准值arr[0]的值丢失了,
                        而key记录着最原本的arr[0]的值,因此我们再将arr[0]的值插入到这个数组中完成了排序。*/

    if(left-1 > low){   //这里当left-1>low就是left-1>0,这说明left左边的数组顺序已经排列好,这里就是要为left右边的数组进行排序
        quick_sort(arr,low,left-1);     //这里的调用相当于递归调用
    }
    if(left+1 < hight){ //原理同上
        quick_sort(arr,left+1,hight);
    }
    return 0;
}

 

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的学生成绩管理系统的二分法实现思路: 1. 将学生信息按照成绩从小到大排序,可以使用冒泡排序快速排序算法来实现。 ``` // 冒泡排序 void bubble_sort(struct student stu[], int n) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (stu[j].score > stu[j + 1].score) { struct student temp = stu[j]; stu[j] = stu[j + 1]; stu[j + 1] = temp; } } } } ``` 2. 实现二分查找算法,用于查询指定成绩的学生信息。 ``` // 二分查找 int binary_search(struct student stu[], int n, float score) { int left = 0, right = n - 1; while (left <= right) { int mid = (left + right) / 2; if (stu[mid].score == score) { return mid; } else if (stu[mid].score > score) { right = mid - 1; } else { left = mid + 1; } } return -1; } ``` 3. 在主函数中实现菜单功能,让用户选择需要的操作。 ``` int main() { int n = 0; printf("请输入学生数量:\n"); scanf("%d", &n); struct student stu[n]; printf("请依次输入每个学生的姓名、学号、成绩:\n"); for (int i = 0; i < n; i++) { scanf("%s %d %f", stu[i].name, &stu[i].id, &stu[i].score); } bubble_sort(stu, n); int choice; float score; while (1) { printf("请选择操作:\n"); printf("1. 查询指定成绩学生的信息\n"); printf("2. 退出程序\n"); scanf("%d", &choice); switch (choice) { case 1: printf("请输入要查询的成绩:\n"); scanf("%f", &score); int index = binary_search(stu, n, score); if (index == -1) { printf("未找到该成绩的学生!\n"); } else { printf("该成绩的学生信息为:\n"); printf("姓名:%s 学号:%d 成绩:%.2f\n", stu[index].name, stu[index].id, stu[index].score); } break; case 2: exit(0); default: printf("输入错误,请重新输入!\n"); break; } } return 0; } ``` 以上是一个简单的学生成绩管理系统的二分法实现思路,具体的实现还需要根据实际情况进行完善和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值