冒泡法、选择法、插入法、二分法

小序

排序是非常重要且很常用的一种操作,有冒泡排序、选择排序、插入排序、希尔排序、快速排序、堆排序等多种方法。这里我们先简单介绍前三种排序算法和代码的实现,其余算法将在后续课程《数据结构》中学习到。算法只是一种思想,其实现依赖于数据结构,所以这里提取出一些典型的算法和数据结构,包括排序以及链表/堆栈/队列等结构的操作。

------------------------------------------------------

冒泡法排序

数组中有N个整数,用冒泡法将他们从小到大(或从大到小)排序。

       实例解析:

   冒泡法排序是C语言教材中已经介绍过的排序方法,与其他排序方法比较起来,冒泡法效率是最低的,但因其算法简单,故也常被采用,其算法是:

   (1)从第一个数开始,相邻两个数两两比较,将大的(或小的)交换到后面,然后继续比较第2、3个数…..当比较完最后两个数的时候,最大数(或最小数)便排在最后了。此过程称为“一趟”。

   (2)将最大数排除在外,其余数重复步骤1。

   (3)重复步骤2,直到所有数都排好为止。

    对于有N个数的排序,上面的过程总共需要进行N-1趟。

   下面是冒泡法排序的代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#include
<stdio.h>

#define 
N 10

int main()

{

    int  a[N]
= {3,5,2,9,7,4,8,1,0,6}, i, j, t;

    for(i
= 0; i < N-1; i++)

    {     //共进行N-1趟

        for(j
= 0; j < N–i-1; j++)  
/*已排好的数据不参与比较
*/

            if(a[j]
> a[j+1])

            {

 
             
t
= a[j];

           
a[j] = a[j+1];

           
a[j+1] = t;

            }

    }

    for(i
= 0; i <= N-1; i++)

        printf(“%3d”,
a[i]);

    printf(“\n”);

    getch();

    return 0;

}


选择法排序

数组中有N个整数,用选择法将他们从小到大排序。

     实例解析:

   选择法是被较多采用的一种排序方法,其效率比冒泡法高(交换数据的次数少),而算法却并未复杂多少。

   选择法排序总的思路是:

   1、找出一个最小数,交换到最前面。

   2、在剩下的数里面,再找一个最小的,交换到剩下数的最前面

   3、重复步骤2 ,直到所有数都已排好。

   显然,对于含有N个数的数组来说,其过程也要进行N-1趟 ( 0 <= i < N-1 )。

   上面所述步骤中,“找出一个最小数,交换到最前面”的方法是:

   先将剩下数中的第一个数(序号是i)作为擂主,用变量k记下其序号,后面的数依次与擂主(注意:擂主是a[k],不总是a[i])比较,若比擂主还小,则用k记下其序号(注意:此时不要交换),当所有数都与擂主比较后,k中存放的就是最小数的序号,然后将它交换到最前面(现在才交换)。在上面的过程中,数据只交换了一次,即每趟只交换一次数据。

   代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#include
<stdio.h>

#define 
N 10

int main()

{

int  a[N]
= {3,5,2,9,7,4,8,1,0,6}, i, j, min, t;

for(i
= 0; i < N-1; i++)

{
 
//共进行N-1趟

/*
首先将最前面数当作擂主,记录其序号 */

 
      min
=
i;
//当进行第i趟时,最前面数的序号是i

/*
后面的每一个数都与擂主进行比较,以便找出最小数 */

for(j
= i+1; j <= N-1; j++)

if(a[j]
< a[k])          
//擂主是a[k],未必总是a[i]

 
              min

= j;                  
//若比擂主还小,则记录其序号

        /*
将最小数交换到(剩下数的)最前面 */

if(min!=i){

        t
= a[k];

        a[k]
= a[i];

        a[i]
= t;

} 

}

for(i
= 0; i <= N-1; i++)

printf(“%3d”,
a[i] );

printf(“\n”);

getch();

return 0;

}



插入排序

   数组中有N个整数,用插入排序实现他们由小到大的排列。

      实例解析:

   插入排序也是常用的一种排序方法,效率较冒泡法高(一趟即可完成),但比选择法低(移动数据次数多)。其基本思想是:将数组分成两个区:前面是已排序的区域(有序区),后面是没有排序的区域(无序区)。每次都从无序区中取第一个数插入到有序区中适当位置,直到所有数据插入完毕为止。

   算法的具体描述是:

   待排序的数据存放在数组A[0, 1, ...N-1]中,未排序前,A[0]自己是一个有序区,A[1, 2, ...N-1]是无序区。程序必须从i = 1开始,直到i = N-1为止,每次将A[i]插入到有序区中。

   插入排序与打扑克摸牌时的理牌过程很相似,当摸来第一张牌时,不需要排序,本身就是排好的(就一张),从第二张开始,每次摸来一张牌,必须插入到原来有序的扑克牌中的适当位置,而为了找到这个适当位置,需要将新摸来的牌与手中的牌进行比较。

   基本的插入排序:

   首先在有序区A[0,1,...i-1]中查找A[i]应该插入的位置k(0 <= k <= i-1),然后将A[k,k+1,...i-1]中的数据各自后移一个位置,腾出位置k插入A[i]。

   若有序区所有数据均小于A[i]时,A[i]就应该在原位置不变,不需要插入。

   改进后的插入排序:

   将待插入的数据A[i]自右至左依次与有序区的数据A[i-1,i-2,...0]进行比较,若A[i]小于某数据A[j],则A[j]后移一个位置,继续与前面的数据比较......直到遇到比A[i]小的数据或前面已没有数据,则插入位置确定。

   若碰到一个数据A[j]比A[i]小,则A[i]应插入到位置j+1。

   若A[i-1]比A[i]小,则A[i]位置不变。

   若所有数据都比A[i]大,则A[i]应插入到位置0。

   下面是改进后插入排序的代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

#define 
N 10

#include
<stdio.h>

int main()

{

int  a[N]
= {3,5,2,9,7,4,8,1,0,6}, i, j, t;

for(i
= 1; i <= N-1; i++)

{

t
= a[i];                     
//保存a[i],因a[i]会被覆盖

for(j
= i-1; a[j]>t && j>=0; j--) 
//
a[j]>t不能写成a[j]> a[i]

a[j+1]
= a[j];

a[j+1]
= t;

}

for(i
= 0; i <= N-1; i++)

printf(“%3d”,
a[i] );

printf(“\n”);

getch();

return 0;

}

二分法排序

二分插入排序实际上是对插入排序的优化。

(1)算法思想

根据插入排序的思想,在插入待排序列的第i个元素时,由于前面的序列已经有序,因此可以使用二分法寻找第i个元素的正确位置。

(2)伪代码:

BinInsertSort(int a[], int n)

{

int key, left, right, middle;

for (int i=1; i<n; i++)

{

key = a[i];

left = 0;

right = i-1;

while (left<=right)

{

middle = (left+right)/2;

if (a[middle]>key)

right = middle-1;

else

left = middle+1;

}

for(int j=i-1; j>=left; j--)

{

a[j+1] = a[j];

}

a[left] = key;

}

}

(3)分析

1)稳定

2)空间代价:Θ(1)

3)时间代价:

插入每个记录需要Θ(log i)比较,最多移动i+1次,最少2次

最佳情况Θ(nlog n),最差和平均情况Θ(n^2)。

时间: 2024-11-09 03:51:09

冒泡法、选择法、插入法、二分法的相关文章

C语言常见的排序方法——冒泡法、选择法、插入法

当我们要对C中一组数据进行排序是常见的排序方法有冒泡法.选择法.插入法 冒泡排序法(升序):假设一组数据a[0].a[1].a[2].a[3]...a[n],第一轮:先比较a[0]与a[1].a[1]与a[2]...a[i]与a[i+1]...a[n-1]与a[n]的大小,如果a[i]与a[i+1]不是升序(即a[i] > a[i+1]),那么就将a[i]与a[i+1]的值互换,第一轮过后,a[n]就是最大值:第二轮:运用第一轮同样的方法,比较a[0]与a[1].a[1]与a[2]...a[i]

php四种基础算法:冒泡,选择,插入和快速排序法

转自:http://www.php100.com/html/php/rumen/2013/1029/6333.html 许多人都说 算法是程序的核心,一个程序的好于差,关键是这个程序算法的优劣.作为一个初级phper,虽然很少接触到算法方面的东西 .但是对于冒泡排序,插入排序,选择排序,快速排序四种基本算法,我想还是要掌握的.下面是我按自己的理解,将四个方法分析一遍. 需求:分别用 冒泡排序法,快速排序法,选择排序法,插入排序法将下面数组中 的值按照从小到的顺序进行排序. $arr(1,43,5

算法学习01:二分查询,选择法、插入法、分治法排序

查询与排序是使用的再频繁不过的两个功能,算法学习系列实现语言为C#. 一般情况下的查询 Int32 Search(Int32[] source, Int32 task) { var index = 0; while (index < source.Length) if (source[index++] == task) return index - 1; //返回值为Length则说明未找到 return source.Length; } 时间复杂度为O(n),在检索源没有排序的情况下,这即为最

冒泡法和选择排序法(比较容易写混)

1 #include<stdio.h> 2 3 4 //冒泡排序法 5 6 void bubbling(int a[],int n); 7 8 //选择排序法 9 void choose(int a[],int n); 10 int main() 11 { 12 int i; 13 int s[6]; 14 printf("please enter five numbers:\n"); 15 for(i=1;i<6;i++) 16 { 17 scanf("%

排序算法(交换法,选择法,插入排序,冒泡法,快速排序算法,C语言举例)

交换法:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. 简单选择排序:的基本思想:第1趟,在待排序记录r[1]~r[n]中选出最小的记录,将它与r[1]交换;第2趟,在待排序记录r[2]~r[n]中选出最小的记录,将它与r[2]交换;以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕. 插入排序法:有一个已经有序的

基于python语言的经典排序法(冒泡法和选择排序法)

前 每逢周末就遇雨期,闲暇之余,捣鼓了下python,心心念想学习,今天就在电脑上装了个2.7,学习了下经典算法,冒泡与选择排序法 第一次写关于python的文章,说的不当之处,多多指正,我积极改正 在之前,曾写过使用java和C语言实现该两种排序法,详情见https://www.cnblogs.com/hong-fithing/p/7615907.html 搭建环境,准备工作就不冗余介绍了,网上搜罗一大堆 目录 冒泡排序法 选择排序法 冒泡排序法 冒泡类似于汽水现象,摇动一下,就有很多泡往上冒

排序 - 选择法

选择法 基本思想, 每一趟 (例如第 i 趟,i = 0, 1, -,n-2)在后面 n-i个待排的数据元素中选出关键字 最小的元素, 作为有序元素序列的第 i 个元素. 排序过程 首先通过n-1次关键字比较,从n个记录中找出关键字最小的记录,将它与第一个记录交换: 再通过n-2次比较,从剩余的n-1个记录中找出关键字次小的记录,将它与第二个记录交换: 重复上述操作,共进行n-1趟排序后,排序结束. 代码: #include <iostream> #include <cstdio>

OJ刷题之《选择法排序》

题目描述 用选择法对10个整数从小到大排序. 输入 10个整数 输出 排序好的10个整数 样例输入 4 85 3 234 45 345 345 122 30 12 样例输出 3 4 12 30 45 85 122 234 345 345 代码如下: #include <iostream> using namespace std; int main() { int i,j,min,temp,a[11]; for (i=0; i<10; i++) { cin>>a[i]; } f

选择法排序/冒泡排序法/交换排序法

这不是个新鲜的话题,是自己之前一直理解错了. int a[10] ={2,4,1,0,9,5,7,6,8,3}; 选择法排序: 第一次循环.a[0] 比较所有的的元素,最小的,跟a0交换 第二次循环,找到剩下的最小的,跟a1 交换 冒泡排序, 也是两层循环 ,  是 1-9, 在内层循环里,是从后往前,这样,一次把最小的一步一步的换到最前来, 比如 a8和a9比较,然后 a7和a8比较,依次.. 说白了,这两种排序,大同小异,时间复杂度是一样的. 交换排序法: 1次循环,跟a0比较,遇到小的,就