精华内容
下载资源
问答
  • 对关键字进行排序c语言
    2021-05-24 08:51:20

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

    请使用"sort.in"作为文件名,且只有1.2.3三个关键字

    #include

    int main()

    {

    int a[1000],b[1000],c[3]={0},temp[1000][2],i,j,n,k=-1,q=0,w=0,e=0,l,u,a2,a3,te=0,d,p;

    FILE *fin=fopen("sort.in","r");

    FILE *fout=fopen("sort.out","w");

    fscanf(fin,"%d",&n);

    for(i=0;i

    {

    fscanf(fin,"%d",&l);

    a[i]=l;

    c[l-1]++;

    }

    for(i=0;i

    for(i=c[0];i

    for(i=c[1]+c[0];i

    for(i=0;i

    if(a[i]!=b[i])

    {

    k=-1;

    for(j=i+1;j

    {

    if((a[j]!=b[j])&&(b[i]==a[j]))

    {

    k=j;

    }

    if((a[j]==b[i])&&(a[i]==b[j]))

    {

    q=a[j];

    a[j]=a[i];

    a[i]=q;

    temp[te][0]=i+1;

    temp[te][1]=j+1;

    te++;

    更多相关内容
  • 利用多关键字排序进行高考分数处理,除了需总分进行排序外,不同的专业单科分数的要求不同,因此在总分相同的情况下,按用户提出的单科分数的次序要求排出考生录取的次序。 假设待排序的记录数不超过1000,表中...
  • 排序算法中的归并排序(Merge Sort)是利用”归并”技术来进行排序。归并是指将若干个已排序的子文件合并成一个有序的文件。 一、实现原理: 1、算法基本思路 设两个有序的子文件(相当于输入堆)放在同一向量中相邻的...
  • 详解C语言中volatile关键字

    千次阅读 2021-09-04 16:37:26
    如 果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举 例说明。在DSP开发中,经常需要等待某个事件的触发,所以经常会...

    转自:https://blog.csdn.net/lwbeyond/article/details/7265430

    volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如 果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举 例说明。在DSP开发中,经常需要等待某个事件的触发,所以经常会写出这样的程序:

    short flag;
    void test()
    {
        do1();
        while(flag==0);
        do2();
    }
    
    

    这段程序等待内存变量flag的值变为1(怀疑此处是0,有点疑问,)之后才运行do2()。变量flag的值由别的程序更改,这个程序可能是某个硬件中断服务程序。例如:如果某个按钮按下的话,就会对DSP产生中断,在按键中断程序中修改flag为1,这样上面的程序就能够得以继续运行。但是,编译器并不知道flag的值会被别的程序修改,因此在它进行优化的时候,可能会把flag的值先读入某个寄存器,然后等待那个寄存器变为1。如果不幸进行了这样的优化,那么while循环就变成了死循环,因为寄存器的内容不可能被中断服务程序修改。为了让程序每次都读取真正flag变量的值,就需要定义为如下形式:

    volatile short flag;

    需要注意的是,没有volatile也可能能正常运行,但是可能修改了编译器的优化级别之后就又不能正常运行了。因此经常会出现debug版本正常,但是release版本却不能正常的问题。所以为了安全起见,只要是等待别的程序修改某个变量的话,就加上volatile关键字。

    volatile的本意是“易变的”
    由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:

    static int i=0;
    int main(void)
    {
        ...
        while (1)
        {
          if (i) do_something();
        }
    }
    
    /* Interrupt service routine. */
    void ISR_2(void)
    {
        i=1;
    }

    程序的本意是希望ISR_2中断产生时,在main当中调用do_something函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致do_something永远也不会被调用。如果变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。

    一般说来,volatile用在如下的几个地方:
    1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
    2、多任务环境下各任务间共享的标志应该加volatile;
    3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
    另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。


    二、volatile 的含义
    volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化,volatile的字面含义是易变的,它有下面的作用:
    1 不会在两个操作之间把volatile变量缓存在寄存器中。在多任务、中断、甚至setjmp环境下,变量可能被其他的程序改变,编译器自己无法知道,volatile就是告诉编译器这种情况。
    2 不做常量合并、常量传播等优化,所以像下面的代码:
    volatile int i = 1;
    if (i > 0) ...
    if的条件不会当作无条件真。
    3 对volatile变量的读写不会被优化掉。如果你对一个变量赋值但后面没用到,编译器常常可以省略那个赋值操作,然而对Memory Mapped IO的处理是不能这样优化的。

    前面有人说volatile可以保证对内存操作的原子性,这种说法不大准确,其一,x86需要LOCK前缀才能在SMP下保证原子性,其二,RISC根本不能对内存直接运算,要保证原子性得用别的方法,如atomic_inc。
    对于jiffies,它已经声明为volatile变量,我认为直接用jiffies++就可以了,没必要用那种复杂的形式,因为那样也不能保证原子性。
    你可能不知道在Pentium及后续CPU中,下面两组指令 :

    inc jiffies
    ;;
    mov jiffies, %eax
    inc %eax
    mov %eax, jiffies 

    作用相同,但一条指令反而不如三条指令快。

    三、编译器优化 → C关键字volatile → memory破坏描述符zz

    “memory”比较特殊,可能是内嵌汇编中最难懂部分。为解释清楚它,先介绍一下编译器的优化知识,再看C关键字volatile。最后去看该描述符。
    1、编译器优化介绍
    内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执行,没有相关性的指令可以乱序执行,以充分利用CPU的指令流水线,提高执行速度。以上是硬件级别的优化。再看软件一级的优化:一种是在编写代码时由程序员优化,另一种是由编译器进行优化。编译器优化常用的方法有:将内存变量缓存到寄存器;调整指令顺序充分利用CPU指令流水线,常见的是重新排序读写指令。对常规内存进行优化的时候,这些优化是透明的,而且效率很好。由编译器优化或者硬件重新排序引起的问题的解决办法是在从硬件(或者其他处理器)的角度看必须以特定顺序执行的操作之间设置内存屏障(memory barrier),linux 提供了一个宏解决编译器的执行顺序问题。
    void Barrier(void)
    这个函数通知编译器插入一个内存屏障,但对硬件无效,编译后的代码会把当前CPU寄存器中的所有修改过的数值存入内存,需要这些数据的时候再重新从内存中读出。
    2、C语言关键字volatile
    C语言关键字volatile(注意它是用来修饰变量而不是上面介绍的__volatile__)表明某个变量的值可能在外部被改变,因此对这些变量的存取不能缓存到寄存器,每次使用时需要重新存取。该关键字在多线程环境下经常使用,因为在编写多线程的程序时,同一个变量可能被多个线程修改,而程序通过该变量同步各个线程,例如:

    DWORD __stdcall threadFunc(LPVOID signal)
    {
        int* intSignal=reinterpret_cast<int*>(signal);
        *intSignal=2;
        while(*intSignal!=1)
        sleep(1000);
        return 0;
    } 

    该线程启动时将intSignal 置为2,然后循环等待直到intSignal 为1 时退出。显然intSignal的值必须在外部被改变,否则该线程不会退出。但是实际运行的时候该线程却不会退出,即使在外部将它的值改为1,看一下对应的伪汇编代码就明白了:

    mov ax,signal
    label:
    if(ax!=1)
    goto label 

    对于C编译器来说,它并不知道这个值会被其他线程修改。自然就把它cache在寄存器里面。记住,C 编译器是没有线程概念的!这时候就需要用到volatile。volatile 的本意是指:这个值可能会在当前线程外部被改变。也就是说,我们要在threadFunc中的intSignal前面加上volatile关键字,这时候,编译器知道该变量的值会在外部改变,因此每次访问该变量时会重新读取,所作的循环变为如下面伪码所示:

    label:
    mov ax,signal
    if(ax!=1)
    goto label 

    3、Memory
    有了上面的知识就不难理解Memory修改描述符了,Memory描述符告知GCC:
    1)不要将该段内嵌汇编指令与前面的指令重新排序;也就是在执行内嵌汇编代码之前,它前面的指令都执行完毕
    2)不要将变量缓存到寄存器,因为这段代码可能会用到内存变量,而这些内存变量会以不可预知的方式发生改变,因此GCC插入必要的代码先将缓存到寄存器的变量值写回内存,如果后面又访问这些变量,需要重新访问内存。
    如果汇编指令修改了内存,但是GCC 本身却察觉不到,因为在输出部分没有描述,此时就需要在修改描述部分增加“memory”,告诉GCC 内存已经被修改,GCC 得知这个信息后,就会在这段指令之前,插入必要的指令将前面因为优化Cache 到寄存器中的变量值先写回内存,如果以后又要使用这些变量再重新读取。
    使用“volatile”也可以达到这个目的,但是我们在每个变量前增加该关键字,不如使用“memory”方便。

    展开全文
  • C语言32个关键字-最详解释

    千次阅读 2020-09-05 16:57:02
    C语言一共有32个关键字,如下表: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch ...

    在了解关键字之前,先要明确定义与声明的区别:
    定义: 编译器创建一个对象,为这个对象分配一块内存并给取一个名字,这个名字成为变量名或对象名。
    声明:告诉编译器,这个名字已经匹配到一块内存上了,其不能再用这个名字进行定义。
    主要区别:定义创建了对象并为这个对象分配了内存,而声明没有分配内存。

    C语言标准定义的32个关键字可以分为如下四类:

    一、数据类型关键字

    序号关键字说明
    1char声明字符变量
    2double声明双精度变量
    3float声明浮点型变量
    4int声明整型变量
    5short声明短整型变量
    6long声明长整型变量
    7unsigned声明无符号类型变量
    8signed声明有符号类型变量
    9struct声明结构体变量
    10union声明共用体或联合数据类型
    11void声明函数无返回值或无参数,声明无类型指针
    12enum声明枚举类型

    重点说明:
    1、chart、short、int、long、float、double
    有一个常被提及的问题:int类型究竟占多少个字节?一般默认为4个字节,而有一点功底的人都知道它的大小是跟机器有关的,感兴趣的可以查看其它文章。int具体大小可用sizeof关键字查看,代码如下:

    # include <stdio.h>
    void main()
    {
    	printf("char类型变量大小为%d字节\n",sizeof(char));
    	printf("short类型变量大小为%d字节\n",sizeof(short));
    	printf("int类型变量大小为%d字节\n",sizeof(int));
    	printf("long类型变量大小为%d字节\n",sizeof(long));
    	printf("float类型变量大小为%d字节\n",sizeof(float));
    	printf("double类型变量大小为%d字节\n",sizeof(double));	
    }
    

    运行结果:

    2、signed、unsigned
    signed和nsigned用于修饰整数类型。默认的int、short、long为有符号数,如signed int 等价于 int(其它类推)。

    另外,char共有三种不同的类型:char、signed char、unsigned char。char类型是真正的字符类型,用来声明字符;而signed char和unsigned char是用来声明数值的。因此不要将三者混用。

    数值范围如下:
    signed char表示范围:[-128, 128);
    unsigned char表示范围:[0, 256);

    3、struct
    在实际问题中,一组数据往往具有不同的数据类型。struct关键字就可以将这些不同数据类型的数据打包成一种构造数据类型。这种构造类型由多个成员组成,每一个成员可以是一个基本数据类型或者另一个构造类型。一般情况下,结构体所占内存大小是其成员所占内存之和。但空结构体的内存大小在不同编译器里有0有1,读者可以试一试。

    4、union
    union关键字用法与struct非常相似,但也有区别。struct中的所有数据成员是共存的,不管有没有调用,编译器都会分配内存;而union中的数据成员是互斥的,它只配置一个足够大的空间来容纳最大长度的数据成员。即union中所有数据成员共用一个空间,同一时间只能存储其中一个数据成员,所有数据成员具有相同起始地址。

    5、void
    void的作用是对函数返回值的限定、对函数参数的限定和声明空类型指针。如果定义函数时不加返回类型限定,则编译器会作为返回整型处理,而不是void, 用void声明的函数表示该函数无返回值;同理,当函数无参数时,可以给无参数函数传送任意类型的参数而不影响程序执行,只有用void指明函数参数时,给无参函数传入参数时编译器才会报错。
    另外,不同数据类型的指针必须经过类型强制转换后才能相互赋值,而void指针可以接受来自任意数据类型的指针赋值,但void指针不能在没有强制类型转换下直接赋值给其它类型的指针。

    二、控制语句关键字

    1、循环语句类型关键字(5个)

    序号关键字说明
    1for遍历循环
    2do其后紧跟循环体
    3while条件循环或死循环
    4break跳出当前循环
    5continue终止本次循环,开始下次循环

    2、条件语句类型关键字(3个)

    序号关键字说明
    6if条件语句
    7else条件语句否定分支
    8goto无条件跳转语句

    重点说明:
    goto语句,有人主张禁用,有人主张慎用,个人认为用来跳出多重循环还是可以的。

    3、开关语句类型关键字 (3个)

    序号关键字说明
    9switch用于多条件判断语句
    10case多条件判断语句分支
    11default开关语句的其它分支

    重点说明:
    switch、case组合语句可以看作为if、else语句的加强版。后者适用于二分支或嵌套较少的分支,前者则在面对多分支情况时有更高的效率。
    case语句需要注意的点很多,如:
    为了避免多个分支重叠,需要在case结尾加上break;
    不要忘了default语句;
    case语句的排序问题等。

    4、返回语句类型关键字(1个)

    序号关键字说明
    12return函数返回语句

    重点说明:
    return用于终止一个函数,并返回其后面跟着的值。

    三、存储类型关键字

    序号关键字说明
    1auto声明自动变量
    2extern声明变量是在其他文件定义
    3register声明寄存器变量
    4static声明静态变量

    重点说明:
    1、auto关键字声明自动变量,由编译器自动分配及释放。这种变量在程序执行时被快速建立,程序退出后被自动撤销,在缺省的情况下,编译器默认所有变量都是auto的。

    2、static为声明静态变量,主要有修饰变量和修饰函数的作用。
    修饰变量时
    变量又分为局部变量与全局变量,当变量被修饰为静态全局变量时,它的作用域为定义之处开始,到文件结尾处结束,其它文件用extern声明也没办法使用它;当变量在函数体内被static修饰,则该变量只能在这个函数里使用,即使是同一个文件也不行,称为静态局部变量。静态变量总是存储在内存静态区,即使是程序执行完毕它的值也不会被销毁。
    修饰函数时
    在函数前面加static可以使函数变为静态函数,静态函数的作用域仅局限于本文件,这样可以避免其它文件中定义的函数重名。
    3、extern 关键字置于变量或函数前,表明变量或函数的定义在其它文件中。链接器在遇到此类变量时会在其它模块中解析/捆绑此标识符。
    4、register
    这个关键字请求 编译器尽可能地将变量存储在cpu的内部寄存器中,而不是通过通过内存寻址来访问变量,这有效地提高了效率。理解这个关键字需要弄那个明白cpu、寄存器与内存之间的关系,cpu是不直接和内存打交道的,cpu与内存之间的数据传输需要经过寄存器,故而将变量存储在寄存器可以提高运行效率。
    PS:寄存器其实就是一块一块小的存储空间,只不过其存储数据要比内存快得多。

    四、其它关键字

    序号关键字说明
    1const声明只读变量
    2sizeof计算数据类型长度(字节数)
    3typedef给数据类型取别名
    4volatile所修饰的对象不能被编译器优化

    重点说明:
    1、const修饰只读变量,变量一旦赋初值就不能被修改。编译器不为只读变量分配内存,这使得它的效率也很高。
    2、sizeof后面常跟这一对括号,但它绝对不是函数,它可以计算数据类型的大小,单位为字节。
    3、typedef的意思是给一个已经存在的数据类型取一个别名,而不是定义新的数据类型。尤其是结构体之类的自定义数据类型,常常需要取一个适用于实际情况的别名。如:

    typedef struct Student
    {
    int a;
    }Stu;
    //这里的Stu实际上就是struct Student的别名
    

    4、volatile是一种类型修饰符,编译器会对它修饰的变量进行特殊地址的稳定访问而不进行代码上的优化。那这里的优化具体指的是什么意思呢?

    比如你想要吃苹果,这时你有两种选择,去苹果园(特殊地址)摘和去商店买,商店里的苹果来自苹果园。所谓的优化实际上是一种“偷懒”行为,当你每次吃苹果都只是去商店买而不去苹果园摘,就是一种优化行为。volatile关键字就是要你每次吃苹果时都只能去苹果园摘而不能去商店买,这就是特殊地址的稳定访问。因为商店里的苹果可能是坏的,已经改变的,而苹果园里的苹果一直都是新鲜的,完好的。

    回到程序里一想,如果你需要某个变量的值稳定,而它又可能在程序执行过程中移到其它地方(商店)时发生改变,为了防止编译器“偷懒”,故你需要在这个关键字前用volatile修饰。

    五、表格汇总

    32个关键字如下:

    autobreakcasecharconstcontinuedefaultdo
    doubleelseenumexternfloatforgotoif
    intlongregisterreturnshortsignedsizeofstatic
    structswitchtypedefunionunsignedvoidvolatilewhile

    【参考文献】
    [1]《C语言深度解剖(第2版)》,作者:陈正冲

    展开全文
  • 主要介绍了C语言中直接插入排序与直接选择排序实现,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,需要的朋友可以参考下
  • 使用C语言实现各种排序

    目录

    1.排序

    (1)排序的稳定性

    (2)内部排序和外部排序

    2.插入排序

    (1)直接插入 排序

    (2)折半插入排序

    (3)希尔排序

    3.冒泡排序

    4.快速排序

    5.简单选择排序

    6.堆排序

    7.归并排序

    8.基数排序

    9.各种排序算法比较总结


    1.排序

    是计算机程序设计中的一种重要的操作,指将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列。

    (1)排序的稳定性

    首先假设两个相同的关键字key1=key2,且在排序之前关键字key1在关键字key2之前;若排序之后的结果是关键字key1任然在关键字key2之前,那么排序是稳定的,否则排序不是稳定的。

    (2)内部排序和外部排序

    内部排序:待排序列记录存放在计算机随机存储器中进行的排序过程(也就是在内存中进行的排序)。

    外部排序:待排记录的数量非常的大,导致内存一次性不能读取全部的记录,所以在排序过程中尚需对外存进行访问的排序过程。

    2.插入排序

    (1)直接插入 排序

    算法思想:从待排序列中将一个关键字插入到排序好的有序表中,从而得到一个新的有序表。

    假设待排记录为:49,38,65,97,76,13,27,49²

    直接插入排序
    初始关键字(49)38659776132749²
    i=2(38)(38,49)659776132749²
    i=3(38)(38,49,65)9776132749²
    i=4(38)(38,49,65,97)76132749²
    i=5(76)(38,49,65,76,97)132749²
    i=6(13)(13,38,49,65,76,97)2749²
    i=7(27)(13,27,38,49,65,76,97)49²
    i=8(49²)(13,27,38,49,49²,65,76,97)
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    #define MAXSIZE 11
    
    typedef int ElemType;
    
    void InsertSort(int a[],int n){
    	for(int i=1;i<n;i++){
    		int temp=a[i];
    		int j=i;
    		while(j>0&&temp<a[j-1]){
    			a[j]=a[j-1];
    			j--;
    		}
    		a[j]=temp;
    	}
    }
    void display(int a[],int n){
    	for(int i=0;i<n;i++){
    		printf("%d\t",a[i]);
    	}
    }
    
    int main(){
    	int array[MAXSIZE];
    	int n;
    	for(int i=0;i<MAXSIZE;i++){
    		array[i]=0;
    	}
    	printf("请输入待排关键字个数: ");
    	scanf("%d",&n);
    	printf("请输入关键字: ");
    	for(int i=0;i<n;i++){
    		scanf("%d",&array[i]);
    	}
    	InsertSort(array,n);
    	display(array,n);
    	return 0;
    }
    /*
    49 38 65 97 76 13 27 49
    */ 

    (2)折半插入排序

    思想:之前的直接插入排序从待排记录中取一个关键字,依次与有序表中的关键字进行比较,查找插入的位置,然而折半插入排序利用有序表的特点,进行折半查找,找到待插入关键字的位置。

    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    #define MAXSIZE 11
    
    typedef int ElemType;
    
    void BinarySort(int array[],int n){
    	for(int i=1;i<n;i++){
    		int left=0;
    		int right=i-1;
    		int temp=array[i];
    		while(left<=right){
    			int mid=(left+right)/2;
    			if(array[i]>array[mid]){
    				left=mid+1; 
    			}else{
    				right=mid-1;
    			}
    		}
    		for(int j=i;j>=left;j--){
    			array[j]=array[j-1];
    		}
    		array[left]=temp;
    	}
    }
    
    void display(int a[],int n){
    	for(int i=0;i<n;i++){
    		printf("%d\t",a[i]);
    	}
    }
    
    int main(){
    	int array[MAXSIZE];
    	int n;
    	for(int i=0;i<MAXSIZE;i++){
    		array[i]=0;
    	}
    	printf("请输入待排关键字个数: ");
    	scanf("%d",&n);
    	printf("请输入关键字: ");
    	for(int i=0;i<n;i++){
    		scanf("%d",&array[i]);
    	}
    	BinarySort(array,n);
    	display(array,n);
    	return 0;
    } 
    /*
    49 38 65 97 76 13 27 49
    */ 

    (3)希尔排序

    思想:先将整个待排记录序列分割成为若干个子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

    希尔排序
    初始关键字4938659776132749²554
    第一趟排序(d=5)132749²5544938659776
    第二趟排序(d=2)13449²38274955659776
    第三趟排序(d=1)413273849²4955657697
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    #define MAXSIZE 15
    
    typedef int ElemType;
    
    void ShellSort(int array[],int n){
    	int temp;
    	int d=n/2;
    	while(d){
    		for(int start=d;start<=2*d&&start<n;start++){
    			//这里面是一个直接插入排序 
    			for(int i=start;i<n;i++){
    				temp=array[i];
    				int j=i;
    				while(j>=d&&temp<array[j-d]){
    					array[j]=array[j-d];
    					j-=d;
    				}
    				array[j]=temp;
    			}
    			d=d/2;
    		}
    	}
    }
    
    void display(int a[],int n){
    	for(int i=0;i<n;i++){
    		printf("%d\t",a[i]);
    	}
    }
    
    int main(){
    	int array[MAXSIZE];
    	int n;
    	for(int i=0;i<MAXSIZE;i++){
    		array[i]=0;
    	}
    	printf("请输入待排关键字个数: ");
    	scanf("%d",&n);
    	printf("请输入关键字: ");
    	for(int i=0;i<n;i++){
    		scanf("%d",&array[i]);
    	}
    	ShellSort(array,n);
    	display(array,n);
    	return 0;
    } 
    /*
    49	38	65	97	76	13	27	49	55	4
    49 38 65 97 76 13 27 49 55 4
    */ 

    3.冒泡排序

    思想:首先将第一个关键字和第二个关键字进行比较,若为逆序,则交换两个关键字,然后比较第二个关键字和第三个关键字,直到第n-1个关键字和第n个关键字进行比较,完成一趟冒泡排序,继续后面的操作直到比较到只有一个关键字为止。

    冒泡排序
    初始关键字4938659776132752
    第一趟排序结果38496576132752(97)
    第二趟排序结果384965132752(76,97)
    第三趟排序结果3849132752(65,76,97)
    第四趟排序结果38132749(52,65,76,97)
    第五趟排序结果132738(49,52,65,76,97)
    第六趟排序结果1327(38,49,52,65,76,97)
    第七趟排序结果13(27,38,49,52,65,76,97)
    第八趟排序结果(13,27,38,49,52,65,76,97)
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    #define MAXSIZE 15
    
    typedef int ElemType;
    
    void BubbleSort(int array[],int n){
    	for(int i=0;i<n;i++){
    		for(int j=0;j<n-i-1;j++){
    			if(array[j]>array[j+1]){
    				int temp=array[j];
    				array[j]=array[j+1];
    				array[j+1]=temp;
    			}
    		}
    	}
    }
    
    void display(int a[],int n){
    	for(int i=0;i<n;i++){
    		printf("%d\t",a[i]);
    	}
    }
    
    int main(){
    	int array[MAXSIZE];
    	int n;
    	for(int i=0;i<MAXSIZE;i++){
    		array[i]=0;
    	}
    	printf("请输入待排关键字个数: ");
    	scanf("%d",&n);
    	printf("请输入关键字: ");
    	for(int i=0;i<n;i++){
    		scanf("%d",&array[i]);
    	}
    	BubbleSort(array,n);
    	display(array,n);
    	return 0;
    } 
    /*
    49	38	65	97	76	13	27	49	55	4
    49 38 65 97 76 13 27 49 55 4
    */ 

    4.快速排序

    思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均另一部分记录的关键字 小,然后再分别对这两部分记录进行排序,以达到整个记录有序。

    快速排序
    初始关键字49,38,65,97,76,13,27,49²
    第一趟排序结果{27,38,13}49{76,97,65,49²}
    第二趟排序结果{13}27{38}49{49²,65}{76}{97}
    第三趟排序结果1327384949²657697
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    #define MAXSIZE 15
    
    typedef int ElemType;
    
    int Pariation(int array[],int low,int high){
    	int temp=array[low];
    	while(low<high){
    		while(low<high&&temp<array[high]){
    			high--;
    		}
    		if(low<high);
    		array[low]=array[high];
    		while(low<high&&temp>=array[low]){
    			low++;
    		}
    		if(low<high)
    		array[high]=array[low];
    	}
    	array[low]=temp;
    	return low;
    }
    
    void QuickSort(int array[],int low,int high,int n){
    	if(low<high){
    		int pivo=Pariation(array,low,high);
    		QuickSort(array,low,pivo-1,n);
    		QuickSort(array,pivo+1,high,n);
    	}
    }
    
    void display(int a[],int n){
    	for(int i=0;i<n;i++){
    		printf("%d\t",a[i]);
    	}
    }
    
    int main(){
    	int array[MAXSIZE];
    	int n;
    	for(int i=0;i<MAXSIZE;i++){
    		array[i]=0;
    	}
    	printf("请输入待排关键字个数: ");
    	scanf("%d",&n);
    	printf("请输入关键字: ");
    	for(int i=0;i<n;i++){
    		scanf("%d",&array[i]);
    	}
    	QuickSort(array,0,n-1,n);
    	display(array,n);
    	return 0;
    } 
    /*
    49 38 65 97 76 13 27 49
    */ 

    5.简单选择排序

    思想:每一趟从n-i+1(i=1,2,……,n-1)个记录中选择最小关键字作为有序序列中第i个记录。

    简单选择排序
    初始关键字235133532
    第一趟排序结果523133532
    第二趟排序结果(5,13)233532
    第三趟排序结果(5,13,23)3532
    第四趟排序结果(5,13,23,32)35
    第五趟排序结果(5,13,23,32,35)
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    #define MAXSIZE 15
    
    typedef int ElemType;
    
    int SelectSort(int array[],int n){
    	for(int i=0;i<n;i++){
    		int min_index=i;
    		for(int j=i+1;j<n;j++){
    			if(array[min_index]>array[j]){
    				min_index=j;
    			}
    		}
    		if(min_index!=i){
    			int temp=array[i];
    			array[i]=array[min_index];
    			array[min_index]=temp;
    		}
    	}
    }
    
    
    
    void display(int a[],int n){
    	for(int i=0;i<n;i++){
    		printf("%d\t",a[i]);
    	}
    }
    
    int main(){
    	int array[MAXSIZE];
    	int n;
    	for(int i=0;i<MAXSIZE;i++){
    		array[i]=0;
    	}
    	printf("请输入待排关键字个数: ");
    	scanf("%d",&n);
    	printf("请输入关键字: ");
    	for(int i=0;i<n;i++){
    		scanf("%d",&array[i]);
    	}
    	SelectSort(array,n);
    	display(array,n);
    	return 0;
    } 
    /*
    49 38 65 97 76 13 27 49
    */ 

    6.堆排序

    思想:首相将待排序列调整为堆大堆根(或者小堆根),由于堆顶一定最大的(或者最小的)关键字,所以将堆顶关键字输出;之后继续对剩下的n-1个关键字继续调整为大堆根(或者小堆根),直到剩下的关键字为0.

    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    #define MAXSIZE 15
     
    void PercolateDown( int pa[],int pos,int size)
    {
    	int p=pos,c=2*p+1;
    	int temp=pa[p];
    	while(c<size)
    	{
    		if(c+1<size&&pa[c+1]>pa[c])
    		{
    			++c;
    		}
    		if(temp>=pa[c])
    		{
    			break;
    		}else
    		{
    			pa[p]=pa[c];
    			p=c;
    			c=2*p+1;
    		}
    	}
    	pa[p]=temp;
    }
    
    void PercolateDown(int pa[],int size)
    {
    	int p=0,c=2*p+1;
    	int temp=pa[p];
    	while(c<size)
    	{
    		if(c+1<size&&pa[c+1]>pa[c])
    		{
    			++c;
    		}
    		if(temp>pa[c])
    		{
    			break;
    		}else
    		{
    			pa[p]=pa[c];
    			p=c;
    			c=2*p+1;
    		}
    	}
    	pa[p]=temp;
    }
    
    void BuildHeap(int pa[],int size)
    {
    	for(int i=size/2-1;i>=0;i--)
    	{
    		PercolateDown(pa,i,size);
    	}
    }
    
    void Heapsort(int pa[],int n)
    {
    	int temp;
    	BuildHeap(pa,n);
    	for(int i=n-1;i>=0;i--)
    	{
    		temp=pa[0];
    		pa[0]=pa[i];
    		pa[i]=temp;
    		PercolateDown(pa,0,i);
    	}
    }
    
    void PercolateUp(int pa[],int pos)
    {
    	int c=pos,p=(c-1)/2;
    	int temp=pa[c];
    	while(c>0)
    	{
    		if(temp<pa[p])
    		{
    			break;
    		}else
    		{
    			pa[c]=pa[p];
    			c=p;
    			p=(c-1)/2;
    		}
    	}
    	pa[c]=temp;
    }
    
    void BuildHeap2(int pa[],int size)
    {
    	for(int i=0;i<size;i++)
    	{
    		PercolateUp(pa,i);
    	}
    }
    
    void Heapsort2(int pa[],int n)
    {
    	int temp;
    	BuildHeap2(pa,n);
    	for(int i=n-1;i>=0;i--)
    	{
    		temp=pa[0];
    		pa[0]=pa[i];
    		pa[i]=temp;
    		PercolateDown(pa,i);
    		//PercolateDown(pa,i)与BuildHeap2(pa,i)等价;
    	}
    }
    int main()
    {
    	int pa[10]={6,7,89,5,12,4,3,2,35,8};
    	printf("向下调整为大堆根并排序:\n");
    	BuildHeap(pa,10);
    	Heapsort(pa,10);
    	for(int i=0;i<10;i++)
    	{
    		printf("%d\t",pa[i]);
    	}
    	printf("\n");
    	printf("向上调整为大堆根并排序:\n");
    	int pa1[10]={6,7,89,5,12,4,3,2,35,8};
    	BuildHeap2(pa1,10);
    	Heapsort2(pa,10);
    	for(int i=0;i<10;i++)
    	{
    		printf("%d\t",pa[i]);
    	}
    	return 0;
    }

    7.归并排序

    思想:假设初始序列为含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后进行两两归并,得到[n/2](向下取整)个长度为2或1的有序子序列;之后再进行两两归并,……,直到归并为长度为n的有序序列为止。

    归并排序
    初始关键字49386597761327
    第一趟归并结果(38,49)(65,97)(13,76)27
    第二趟归并结果(38,49,65,97)(13,27,76)
    第三趟归并结果(13,27,38,49,65,76,97)

    归并排序

    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    #define MAXSIZE 11
    
    typedef int ElemType;
    int merge[MAXSIZE];
    
    //合并两个有序子序列
    void Merge(int merge[],int a[],int left,int right,int middle){
    	int i=left,j=middle+1;
    	int k=left;
    	while(i<=middle&&j<=right){
    		if(a[i]<=a[j]){
    			merge[k++]=a[i++];
    		}else{
    			merge[k++]=a[j++];
    		}
    	}
    	while(i<=middle)merge[k++]=a[i++];
    	while(j<=right)merge[k++]=a[j++];
    	i=0;
    	for(i=left;i<=right;i++)a[i]=merge[i];
    }
    //合并排序算法
    void Mergesort(int a[],int left,int right){
    	if(left<right){
    		int middle=(left+right)>>1;
    		Mergesort(a,left,middle);
    		Mergesort(a,middle+1,right);
    		Merge(merge,a,left,right,middle);
        }
    }
    void display(int a[],int n){
    	for(int i=0;i<n;i++){
    		printf("%d\t",a[i]);
    	}
    }
    
    int main(){
    	int array[MAXSIZE];
    	int n;
    	for(int i=0;i<MAXSIZE;i++){
    		array[i]=0;
    	}
    	printf("请输入待排关键字个数: ");
    	scanf("%d",&n);
    	printf("请输入关键字: ");
    	for(int i=0;i<n;i++){
    		scanf("%d",&array[i]);
    	}
    	Mergesort(array,0,n-1);
    	display(array,n);
    	return 0;
    } 
    /*
    49 38 65 97 76 13 27 49
    */ 

    8.基数排序

    基数排序

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

     

    在这里插入图片描述

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<list>
    using namespace std;
    const int maxx=10;
    int pa[maxx];
    int n;
    template<class T>
    class Queue{
    	private:
    		list<T>q;
    	public:
    		int Size(){return q.size();}
    		int Empty(){return q.empty();}
    		void Clear(){return q.clear();}
    		void Push(const T&item){q.push_back(item);}
    		T Pop(){T item=q.front();q.pop_front();return item;}
    };
    void Radixsort(int n){
    	Queue<int>q[10];//10个箱子
    	int base=1,flag=1,k;
    	while(flag){
    		for(int i=0;i<n;i++){//分配
    			k=(pa[i]/base)%10;
    			q[k].Push(pa[i]);
    		}
    		base*=10;//晋级到更高一位
    		flag=0;//每趟收集前,令flag=0
    		int i=0;
    		for(k=0;k<10;k++){//收集
    			while(!q[k].Empty()){
    				pa[i++]=q[k].Pop();
    				if(pa[i-1]/base!=0&&flag==0){
    					flag=1;//还有更大的数位
    				}
    			}
    		}
    	}
    }
    int main(){
    	while(scanf("%d",&n)!=EOF){
    		for(int i=0;i<n;i++){
    			scanf("%d",&pa[i]);
    		}
    		Radixsort(n);
    		for(int i=0;i<n;i++){
    			cout<<pa[i]<<" ";
    		}
    	}
    	return 0;
    }
    

    9.各种排序算法比较总结

    排序算法 比较
    排序方法平均时间最坏情况辅助空间稳定性
    直接插入排序O(n²)O(n²)O(1)稳定
    折半插入排序O(n²)O(n²)O(1)稳定
    希尔排序不稳定
    简单选择排序O(n²)O(n²)O(1)稳定
    快速排序O(nlogn)O(n²)O(logn)不稳定
    堆排序O(nlogn)O(nlogn)O(1)不稳定
    归并排序O(nlogn)G(nlogn)O(n)稳定
    基数排序O(d(n+rd))O(d(n+rd))O(rd)稳定

    参考数据:《数据结构》清华大学

    展开全文
  • 生成一组无序关键字,用C语言输出快速排序过程中消耗的额外空间
  • C语言中volatile关键字用法

    千次阅读 2021-03-06 18:10:52
    介绍Volatile关键字之前我们先了解一下编译器的优化。 高速缓存:处理器读取程序里面的数据时,把一些访问频率比较高的数据,临时存储到寄存器(register)中,当需要取数据时,就会从 register 中取,而不是直接去从...
  • // main.cpp// select_sort//// Created by duanqibo on 2019/7/17.// Copyright © 2019年 ... All rights reserved.// 选择排序 c语言#include #include #include #include #define N 10typedef struct student...
  • C语言常用排序法----结合顺序表

    千次阅读 2018-11-28 23:14:23
    首先定义顺序表,实现由小到大的排序 typedef int ElemType ; typedef struct { ElemType *elem; int length; int listsize; }SqList;//SqList是结构体名字 L.length为数组长度 冒泡排序法:将每...
  • 用qsort函数结构体数据进行排序
  • 关键字排序

    2022-06-30 21:42:33
    时间:1s 空间:32M 题目描述: 给你n对数,把它们先按照第一个数的升序排序,如果第一个数相等就按照第二个数的升序排序。 输入格式: 第一行输入一个整数n 接下来n行每行输入两个整数ai,bi 输出格式: 按照升序...
  • 基本的排序算法有如下几种:交换排序(冒泡排序、快速排序)、选择排序(直接选择排序、堆排序)、插入排序(直接插入排序、希尔排序)、归并排序、分配排序(基数排序、箱排序、计数排序)。下面依次列出各种算法的...
  • C语言volatile关键字

    2017-09-22 11:25:37
    C语言volatile关键字
  • 1)C 语言 各种变量、函数等命名时使用的字符序列称为标识符 2)凡是自己可以起名字的地方都叫标识符 标识符的命名规则 1)由 26 个英文字母大小写,0-9 ,_或 $ 组成 2)数字不可以开头。 3)不可以使用关键字和...
  • C语言中数据结构之链式基数排序 实现效果图: 实例代码: #include #include #include #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 typedef int Status; typedef int ...
  • 一.前言1.编译器优化介绍:由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序...
  • 冒泡排序 C语言(从大到小排序

    千次阅读 2022-02-05 14:58:46
    也就是说 定义arr[5]只是 为了 让你知道这个数组大小是 5 而已 我们在访问 数组的元素地址时候 是用下标来访问的 (从0开始 ) 上述的两种定义的方法 都可以适用在我们的元素长度和数组大小不上时 他们自动补充 ...
  • 在有多个条件的情况下排序,我们一般用结构体cmp来排序。这个时候你就需要想一想,会不会有些题就卡你的这个排序的时间呢?所以我们需要想一想怎么来优化我们的代码。 现在想一想,怎么来优化。我举个例子: 有n个数...
  • 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。  当n较大,则应...
  • C语言32个关键字44种运算符整理分割线 卡通人物32个关键字,如下表所示:关键字说明auto声明自动变量short声明短整型变量或函数int声明整型变量或函数long声明长整型变量或函数float声明浮点型变量或函数double声明...
  • 详解C语言中const关键字的用法关键字const用来定义常量,如果一个变量被const修饰,那么它的值就不能再被改变,我想一定有人有这样的疑问,C语言中不是有#define吗,干嘛还要用const呢,我想事物的存在一定有它自己...
  • c语言中的关键字和保留字的区别?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!c语言中的关键字和保留字的区别?在C语言中,关键字与保留字表示同一...
  • 按照主关键字和次关键字排序

    千次阅读 2014-04-05 14:11:43
    #include #include ...void quick_sort(int *s,int *f,int low,int high)//快速排序,安装活动的开始时间升序排序 { while (low){ int pivot=s[high]; int k=low-1; int tmp; for(int i=low;i;+
  • 实现以下排序插入排序O(n^2) 冒泡排序 O(n^2) 选择排序 O(n^2) 快速排序 O(n log n) 堆排序 O(n log n) 归并排序 O(n log n) 希尔排序 O(n^1.25) 1.插入排序 O(n^2) 一般来说,插入排序都采用in-place在数组上实现。...
  • C语言中volatile关键字的作用
  • qsort 函数是C语言提供的库排序函数,除了解决传统的int数组排序以外,还可以字符串、结构体等进行排序。这里qsort函数也体现了之前说过的回调函数的机制 在库中长这么个样子: void qsort ( void * base, ...
  • 比如:一组数排序前是a1,a2,a3,a4,a5,其中a2=a4,经过某种排序后为a1,a2,a4,a3,a5,则我们说这种排序是稳定的,因为a2排序前在a4的前面,排序后它还是在a4的前面。假如变成a1,a4,a2,a3,a5就不是稳定的了。 2、内...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,029
精华内容 14,811
热门标签
关键字:

对关键字进行排序c语言