• 交换类排序总结


    交换类排序总结

    顾名思义,交换类排序,也就是通过一系列的交换元素过程,把原本逆序的元素交换为正确的顺序的排序方法

    一.简单的交换类排序——冒泡排序

    通过多趟的扫描,每趟扫描过程中,将相邻的元素中较大的交换至后面,这样每一趟结束时,最大的那个元素就“沉”到最后面,通过n-1趟的交换,直到只剩下一个元素在最前面,已经不需要交换了,完成排序

    不过,冒泡排序写代码的时候要注意优化,下面是非优化版本

    简单版本的冒泡排序

    void Bubble_Sort(int a[],int n)
    {
    	for (int i = 1; i <= n-1; i++)
    	{
    	
    		for (int j = 0; j < n-i; j++)
    		{
    			if (a[j]>a[j+1])
    			{
    				int temp=a[j+1];
    				a[j+1]=a[j];
    				a[j]=temp;
    			
    			}
    		}
    
    	}
    }
    

      

    时间复杂度分析:这样看来,冒泡的最好时间复杂度和最坏时间复杂度都为O(n²);

    最好的情况其实是可以优化的,那就是加入元素已经是排好序的话,我们可以用一个标志量来控制

    void Bubble_Sort(int a[],int n)
    {
    	bool change=true;
    	for (int i = 1; i <= n-1&&change; i++)
    	{
    		change=false;
    		for (int j = 0; j < n-i; j++)
    		{
    			if (a[j]>a[j+1])
    			{
    				int temp=a[j+1];
    				a[j+1]=a[j];
    				a[j]=temp;
    				change=true;
    			}
    		}
    
    	}
    }
    

      

    这样看来,冒泡排序的最好时间复杂度为O(n)了,外层循环实际上不进行了,只执行i=1的时候,因为元素是排好序的

    最坏情况:仍然为O(n²)

    二.快速排序(QuickSort)

      我们可以回头过来看冒泡排序,通过它来理解所谓的比较排序到底是怎么一种思想,冒泡排序是通过不停地比较相邻的元素来排序,在一趟又一趟的扫描过程中完成排序,在这一过程中,比较是精髓和关键点,但是,在冒泡排序的比较过程中,我们可以发现,它每次只能比较相邻的元素,这样来看,效率是比较低的,能不能一次比较多个数来提高效率呢,快速排序的思想就是这样的,一趟比较多个元素

                快速排序的思想

         1.选取一个数作为标杆(选取第一个数),将数组中大于标杆数的元素都放到标杆数的右边,数组中小于标杆数的元素都放到标杆数的左边,记录下标杆数的位置

        2.依据标杆数的位置,对标杆数左边的子数组重复第一步,直到左边只剩下一个数字

        3.依据标杆数的位置,对标杆数左边的子数组重复第一步,直到左边只剩下一个数字

    这样就完成了大名鼎鼎的快速排序,同时做到了一次排多个数字

        一趟快速排序的实施步骤:

          1.选取第一个数字作为标杆数,令low=其下标,令high=最后一个数字的下标,暂存变量x=a[low];

          2从high到low遍历,将小于x的数字全部移到x的左边

          3.从low到high遍历,将大于x的数字全部移到x的右边

          4.当low=high的时候,停止遍历,最后返回标杆数x的位置

        快速排序的实施步骤:

          1.求得原数组标杆数的位置

          2.利用标杆数位置,递归调用左边的子数组

          3.利用标杆数位置,递归调用右边的子数组

    具体代码如下:

    int Quick_Sort_Once(int a[],int low,int high)
    {
    	int x=a[low];
    	while(low<high)
    	{
    		while(low<high&&a[high]>=x)
    		{
    			high--;
    		}
    		if(low<high)
    		{
    			
    			a[low]=a[high];
    			low++;
    		}
    		while(low<high&&a[low]<x)
    		{
    			low++;
    		}
    		if(low<high)
    		{
    			a[high]=a[low];
    			high--;
    		}	
    	}
    	a[low]=x;
    	return low;
    }
    void Quick_Sort(int a[],int low,int high)
    {
    	if(low<high)
    	{
    		int x=Quick_Sort_Once(a,low,high);
    		Quick_Sort(a,low,x-1);
    		Quick_Sort(a,x+1,high);
    	
    	}
    }
    

      

    注意事项:注意Quick_Sort()函数中if(low<high)容易漏掉,这个必须有,不然,就会有无限递归调用,递归栈就会超出内存,程序崩溃

    时间复杂度分析:

    最坏的情况是:原数组本来就有序,这时候,左边子数组总是为空,右边子数组为n-1,所以总的时间复杂度为n-1+n-2+n-3+....+1=O(n²),即最坏的时间复杂度为O(n²);

    最好的情况是:数组的第一个数正好是中间大的,这时候总的时间复杂度为:T(n)=O(n)+2T(n/2),根据这个式子可以推导出最好的时间复杂度为O(nlog2(n));

    空间复杂度分析:

    一般空间复杂度假如没有的递归的话为O(1),有递归的话那就看递归栈的深度了,递归栈的深度,那就看递归进层能有多深,这个递归明显是个二叉树式的递归,最好的情况是个满二叉树,因此树的深度就为递归栈的深度(最大只需要容纳几次push),树的深度为log2(n),所以空间复杂度为log2(n);

    稳定性:不稳定

    举个栗子:5644;

    明显排序的时候后一个4是先填坑的,填到了5这个位置,这样一来他们的 顺序就颠倒了,所以是不稳定的,类似这样的情况时,他们都是不稳定的

    亲爱的听众朋友我是你的代班DJ
  • 相关阅读:
    Ubuntu16.04 LTS 安装VNC Server开启远程桌面
    duilib List右键菜单的响应
    centos bootloader安装到u盘后修复方法
    dpkg: error processing package XXX (--configure) 解决方法 (ubuntu右上角红色警告)
    linux centos ftp服务器搭建
    windows 端口转发 netsh
    遍历windows窗口
    解除文件占用
    VS 运行库MT、MD的区别
    点击显示桌面的窗口状态
  • 原文地址:https://www.cnblogs.com/YTYMblog/p/6099760.html
Copyright © 2020-2023  润新知