常用排序算法:冒泡、插入、快速、选择排序

1、冒泡排序:

比较两个相邻的元素,将值大的元素交换到右边

   基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉较小的往上冒。  即:每当两相邻的数比较后发现它们当前排序与排序要求相反时,就将它们互换,即一轮比较后,较大的数被移动到最后面......

   从前往后,依次比较相邻的两个数,把较大的数放到后面。一次循环,可以在当前最末尾位置得到一个当前的最大值。

 

  ==》时间复杂度  ==》平方级  

  for(i=0;i<n-1;i++)
    {
        for(j=0;j<n-1-i;j++)
        {
            if(a[j] > a[j+1])
            {
                t = a[j];
                a[j] = a[j+1];
                a[j+1] = t;
            }
        }
    }

 

2、选择排序:

从数组中找出最小数放在第1个位置,第二个最小数放在第2个位置;

(1)基本思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

    2.1小数上浮(先选小数排列,i=0;)

   1)假设数组中的第1个数是最小的数(下标为min),2)然后依次与剩余的数进行比较,若还有比第1个数小的数,则该数为最小的数(该数的下标赋值该min);3)第一轮运行结束后,判断min的下标是否改变,若改变,则交换数据:最小的数放到前面。

   【设定最小元素为首元素,则与后续元素比较,刷新最小的元素,最终由小到大排序】

   

    for(i=0;i<n;i++)				//【查找的轮数/次数】
    {
        min = i;
        for(j=i+1;j<n;j++)		//若i后面的元素有比min小的,则上浮
        {
            if(a[min] > a[j])
					min = j;
        }
        if(min != i)				//上浮数据处理
        {
           t = a[i];
           a[i] = a[min];
           a[min] = t;  
        }
    }

 

    2.2 大数下沉(先选大数排列,i=n-1;)

   //【设定最后一个元素为最大数,之后与其余元素比较,找到最大数放至最后】

   

for(i=n-1;i>=0;i--)
    {
        max = i;
        for(j=i;j>=0;j--)
        {
            if(a[max] < a[j])
					max = j;
        }
        
	    if(max != i)
        {
            t = a[i];
            a[i] = a[max];
            a[max] = t;
        }
    }

3、插入排序

   基本思想:在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

   插入排序原理:将一组数据分成两组,分别将其称为有序组与待插入组。每次从待插入组中取出一个元素,与有序组的元素进行一一比较(将大数向后移动),并找到合适的位置,将该元素插到有序组当中。

   就这样,每次插入一个元素,有序组增加,待插入组减少。直到待插入组元素个数为0。当然,插入过程中涉及到了元素的移动。

4  6  2  5  // 原有数列

4  7  6  2  5  ==》  i=2;  4  6  7  2  5;

4  6  7  2  5  ==》  i=3;4   6  5;   6  7  5

int insert_sort(int a[],int n)
{¯
    int i =0,j=0,t=0;

    for(i=1;i<n;i++)	//i=1;插入时,因假设第a[0]个数据为有序数列
    {
        t = a[i];		// 先保存待插入的数据,将该数与前面有序队列的每一个数进行比较,若有序数列比待插入的数大,则有序数列中的数向后移动,直到有序数列中数没有比待插入的数大的,则插入
        for(j=i; ((j>0) &&(a[j-1] > t));j--)
        {
				// if((a[j-1] > t) 
            	a[j]= a[j-1];	// 与签名有序数列比较,将大数向后移动
        }
        a[j] = t;	// 有序数列中数没有比待插入的数大的,则插入
    }
    return 0;
}

insert_sort(a,sizeof(a));

 

4、快速排序

   思路分析:快速排序采用双向查找的策略,每一趟选择当前所有子序列中的一个关键字作为枢纽轴(或者基准数据),将子序列中比枢纽轴小的前移,比枢纽轴大的后移,当本趟所有子序列都被枢轴按上述规则划分完毕后将会得到新的一组更短的子序列,他们将成为下趟划分的初始序列集。

   时间复杂度:最好情况(待排序列接近无序)时间复杂度为O(nlog2n),最坏情况(待排序列接近有序)时间复杂度为O(n2),平均时间复杂度为O(nlog2n)。

int  quick_sort(int a[],int head,int tail)
{
    int x = a[head];				// 基准数据备份
    int i = head,j = tail;		// 头、尾下标标记
    while(i<j)
    {
        while(i<j)
        {
            if(a[j] >= x) j--;	// 从后往前比较
            else
            { a[i] = a[j]; break;}
        }
        while(i<j)
        {
            if(a[i] <= x) i++;	//	从前往后比较
            else{ a[j] = a[i];break;}
        }
    }
    a[i] = x;	// 放入基准数据
    if(head < (i-1)) quick_sort(a,head,i-1);
    if((i+1)< tail)  quick_sort(a,i+1,tail);
}

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值