一文搞懂冒泡排序、快速排序、选择排序

目录

冒泡排序:

快速排序:

 选择排序:


冒泡排序:

  • 核心思想:两个相邻的元素进行比较

  • 分析过程:

  • 易错点:
    1.传递的参数是数组和数组的个数(长度)--数组的个数无法在函数内部计算
    2.双层的for循环,第二层的for循环中:j是随着i变化的
  • void bubble_sort(int arr[],int nlen)//形参是数组的形式
    {
    	for (int i = 0; i < nlen - 1; i++)//一共交换多少趟
    	{
    		for (int j = 0; j < nlen - 1 - i; j++)//每趟里面的元素交换
    		{
    			if (arr[j] > arr[j + 1])
    			{
    				//交换
    				int temp = arr[j];
    				arr[j] = arr[j + 1];
    				arr[j + 1] = temp;
    			}
    		}
    	}
    }
    
    int main()
    {
    	//int arr[] = { 9,8,7,6,5,4,3,2,1 };
    	int arr[] = { 5,1,4,7,0,9,11,73,54 };
    	int nlen = sizeof(arr) / sizeof(arr[0]);
    	bubble_sort(arr,nlen);//传进来的数组是数组首元素的地址
    	for (int i = 0; i < nlen; i++)
    	{
    		printf("%d ", arr[i]);
    	}
    	printf("\n");
    	return 0;
    }

    快速排序:

  • 核心思想:通过一趟排序,将待排元素分割成两个独立的部分,分别对这两部分进行排序,达到有序。

  • 步骤:挖坑填数法!+分治的思想
    1.先找到基准元素(1),把比基准元素小的,放到基准元素的左边;把比基准元素大的,放到基准元素的右边,此时将基准元素(1)排到正确的位置
    2.寻找新的基准元素(2),递归实现
    3.寻找新的基准元素(3),递归实现

  • 图文分析:

int AdjustArray(int s[], int l, int r) //返回调整后基准数的位置
{
    int i = l, j = r;
    int x = s[l]; //s[l]即s[i]就是第一个坑
	//由于s[l]这个位置的数被记录下来了,所以可以认为这个位置是一个坑
    while (i < j)
    {
        // 从右向左找小于x的数来填s[i]
        while(i < j && s[j] >= x) 
            j--;  
        if(i < j) 
        {
            s[i] = s[j]; //将s[j]填到s[i]中,s[j]就形成了一个新的坑
            i++;
        }
 
        // 从左向右找大于或等于x的数来填s[j]
        while(i < j && s[i] < x)
            i++;  
        if(i < j) 
        {
            s[j] = s[i]; //将s[i]填到s[j]中,s[i]就形成了一个新的坑
            j--;
        }
    }
    //退出时,i等于j。将x填到这个坑中。
    s[i] = x;//此时基准元素被放到正确的位置上
 
    return i;//返回基准元素的位置
	//下一次在排序的时候,排基准元素的左边和右边
	//排基准元素的左边,下标就是left = 0  right = i-1
	//排基准元素的右边,下标就是left = i+1 right = nlen-1
}
void quick_sort1(int s[], int l, int r)
{
    if (l < r)
    {
        int i = AdjustArray(s, l, r);//先成挖坑填数法调整s[]
        quick_sort1(s, l, i - 1); // 递归调用 
        quick_sort1(s, i + 1, r);
    }
}

//快速排序
void quick_sort(int s[], int l, int r)
{
    if (l < r)
    {
        //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
        int i = l, j = r, x = s[l];
        while (i < j)
        {
            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
                j--;  
            if(i < j) 
                s[i++] = s[j];
            
            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
                i++;  
            if(i < j) 
                s[j--] = s[i];
        }
        s[i] = x;
        quick_sort(s, l, i - 1); // 递归调用 
        quick_sort(s, i + 1, r);
    }
}
  •  易错点:
    1.基准元素的位置被记录下来了,可以理解为这个下标位置是个坑,可以填写其他的数
    2.求基准元素的函数中,第二个while循环中,if语句中表达的是基准元素的左边/右边的待排元素就只剩余一个的情况,应该先把基准元素放到这个坑中,再移动下标!!
  • 性能分析:
    1.空间效率:最好O(log2的n方) 最坏O(n) 平均O(log2的n方)
       时间效率:最好O(nlog2的n方) 最坏O(n平方) 平均O(nlog2的n方)
    2.快排是内部排序中平均性能最优的算法
    3.稳定性:不稳定性(输入数据次序越乱,排序的速度越快)
       (1)不适用于对原有序或基本有序的数据进行排序
       (2)基准元素的选取直接影响时间性能

 选择排序:

  • 核心思想:遍历数组,每次找到最小的放到对应位置
  • 分析步骤:
    1.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
    2.再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
    3.重复第二步,直到所有元素均排序完毕。
void swap(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}
void select_sort(int arr[], int nlen)
{
	for (int i = 0; i < nlen - 1; i++)//数组是从下标0开始的
	{
		int min = i;//min是数组的下标
		//遍历i之后的元素,看看是否有比arr[i]小的,如果有就交换
		for (int j = i + 1; j < nlen; j++)
		{
			if (arr[min] > arr[j])
			{
				min = j;//赋值语句,记录最小值的下标   
			}
		}
		//交换
		swap(&arr[min], &arr[i]);
	}
}
  • 易错点:
    1.swap函数注意参数的传递方式:地址传递(值传递,形参的修改不会影响实参)
    2.注意swap函数的位置是在第二个for循环的外边:遍历数组找到最小的值才会交换一次
  • 性能分析:
    1.时间复杂度:O(n的方)
    2.使用:数据规模越小越好
    3.好处:不占用额外的空间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>