排序与查找算法(C语言描述)


C++自带的algorithm库函数中提供了排序算法。
自带排序算法的一般形式为:
sort(arr+m,arr+n);//将数组arr的下标为m的元素到下标为n-1的元素进行从小到大排序
sort(arr+m,arr+n,comp);//与sort(arr+m,arr+n)相比,这个写法可以自己定义排序的规则,其中,comp为自定义的函数


排序算法

选择排序

基本思想:
选择排序(从小到大)的基本思想是,首先,选出最小的数,放在第一个位置;然后,选出第二小的数,放在第二个位置;以此类推,直到所有的数从小到大排序。

在实现上,我们通常是先确定第i小的数所在的位置,然后,将其与第i个数进行交换。

评价:
注意:选择排序是一种不稳定的排序算法,可能会打乱两个相同数字的原有顺序。

例如,序列 5 8 5 2 9, 按照从小到大排序,第一轮会将第1个数字5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序是一种不稳定的排序算法。

#include <stdio.h> 
#include <stdlib.h>
#include <time.h>
const int MAXN = 10;

int main (void)
{
    int a[MAXN] = {0};
    int i = 0;
    int j = 0;

    srand( (unsigned)time(NULL) );//rand()函数产生的是伪随机数(产生原理是 F(种子值),也就是关于一个固定值的固定公式;
                                  //也就是程序运行第一次和第二次产生的随机数是一样的,所以我们要利用srand()进行播种;srand(unsigned seed)
    for (int k = 0; k < MAXN; k++) {
        a[k] = rand()%100 + 1;
    }

    printf("初始化数组:");
    for (i = 0; i < MAXN; i++) {
        printf("%-2d ", a[i]);
    }
    printf("\n");

    /*----------*/
    //选择排序原理:
    //1、从第一个数开始(a[0]),找到数组中最小的数的位置,然后交换第一个数和最小数
    //2、从第二个数开始(a[1]),找到剩余数中最小数的位置(对应整个数组第二小的数),然后交换第二个数和最小数
    //......
    //N-1、从第N-1个数开始(a[MAXN-1]))、最后一次,比较最后两数了。

    //外循环:对应找第一个位置上的最小数,第二个,...,当前N-1个都找好了,最后一个自然不用找了,
    //        故边界条件为 0 ~ MAXN-1 ,共 N-1次;
    //内循环:要完成的任务是:遍历数组元素找到最小值;交换该位置数和最小值所在位置数,如果是本身就不用交换;
    //        起点对应第一小的数放在第一个位置,第一个数也要遍历到;
    //        但是我是用第一个数最为参照进行比较的,所以起点i = j + 1,直接与下一个数进行比较即可,一直到最后一个数;
    //交换数:采用位运算中的异或运算交换两个不同的数;
    //        原理:a^b^b = a;

    /*-------  -*/
    for (j = 0; j < MAXN - 1; j++) {
        int min_index = j;
        for (i = j + 1; i < MAXN; i++) {
            if (a[min_index] > a[i]) {
                min_index = i;
            }
        }
        if (j != min_index) {
            a[j] = a[j] ^ a[min_index];
            a[min_index] = a[j] ^ a[min_index];
            a[j] = a[j] ^ a[min_index];
        }
    }

    printf("排序后数组:");
    for (i = 0; i < MAXN; i++) {
        printf("%-2d ", a[i]);
    }
    putchar('\n');

    return 0;
}
#include <cstdio> 
#include <cstdlib>
#include <ctime>
const int size = 10;

void select_sort(int a[], int MAXN) {

    printf("初始化数组:");
    for (int i = 0; i < size; i++) {
        printf("%-2d ", a[i]);
    }
    printf("\n");

    //核心部分 
    for (int j = 0; j < MAXN - 1; j++) {
        int min_index = j;
        for (int i = j + 1; i < MAXN; i++) {
            if (a[min_index] > a[i]) {
                min_index = i;
            }
        }
        if (j != min_index) {
            a[j] = a[j] ^ a[min_index];
            a[min_index] = a[j] ^ a[min_index];
            a[j] = a[j] ^ a[min_index];
        }
    }

    printf("排序后数组:");
    for (int i = 0; i < size; i++) {
        printf("%-2d ", a[i]);
    }
    putchar('\n');
}

int main (void)
{
    int a[size];
    //初始化数组
    srand( (unsigned)time(NULL) );
    for (int k = 0; k < size; k++) {
        a[k] = rand()%100 + 1;
    }
    select_sort(a, size);//排序 
    return 0;
}

冒泡排序

基本思想
冒泡排序(从小到大)的基本思想是,不断比较相邻的两个数,让较大的元素不断的往后移,经过一轮比较,就选出最大的数;经过第二轮比较就选出次大的数,以此类推。

一般实现

#include <cstdio> 
#include <cstdlib>
#include <iostream>
#include <ctime>
const int size = 10;

void select_sort(int a[], int MAXN) {
    int i;

    printf("初始化数组:");
    for (i = 0; i < size; i++) {
        printf("%-2d ", a[i]);
    }
    printf("\n");

    /*--------*/
    //基本思想:第一轮,比较a[0]和a[1],如果a[0]>a[1],则交换两数,接着比较a[1]和a[2],......最后一次为a[N-2]和a[N-1]的比较,至此,a[N-1]为最大数
    //          第二轮,比较a[0]和a[1], ......最后一次为a[N-3]和a[N-2]的比较
    //          .......
    //          第N-1轮,比较a[0]和a[1],结束排序
    // 外循环: 0~szie-1 共 N -1 轮
    // 内循环: 总是从0和1开始比较的,故初始值j=0开始,比较到size - 1 - i;
    //          
    //两轮循环的循环变量的意义不同,一个是轮数,一个数数组元素下表  注意理解二者的区别和联系
    /*--------*/
    for (i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - 1 - i; j++) {
            if (a[j] > a[j+1]) {
                a[j]   = a[j] ^ a[j+1];
                a[j+1] = a[j] ^ a[j+1];
                a[j]   = a[j] ^ a[j+1];
            }
        }
    }

    printf("排序后数组:");
    for (i = 0; i < size; i++) {
        printf("%-2d ", a[i]);
    }
    putchar('\n');
}

int main (void)
{
    int a[size];
    //初始化数组
    //srand( (unsigned)time(NULL) );
    for (int k = 0; k < size; k++) {
        a[k] = rand()%100 + 1;
    }

    select_sort(a, size);//排序

    return 0;
}

优化实现

for (i = 0; i < size - 1; i++) {
        bool isSorted = true; //
        for (int j = 0; j < size - 1 - i; j++) {
            if (a[j] > a[j+1]) {
                isSorted = false; //
                a[j]   = a[j] ^ a[j+1];
                a[j+1] = a[j] ^ a[j+1];
                a[j]   = a[j] ^ a[j+1];
            }
        }
        if (isSorted) {  
            break; // 本轮冒泡没用进行交换,代表已经排序完成,不用再继续冒泡了。
        }
    }

评价
优点:稳定;
缺点:慢,每次只能移动相邻两个数据。

快速排序

归并排序

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值