交换排序——冒泡排序和快速排序

这里的测试数据来自于之前自己随便写的生成器https://blog.csdn.net/qq_37350078/article/details/101561041

#include<bits/stdc++.h>
using namespace std;

int main() {
	FILE *fp;
    if((fp = fopen("test.txt", "r")) == NULL)  
    	{ cout << "Error!"; }
    int T = 10, arr[20];
    while(T--) {//多组样例 
    	for(int i = 1; i <= 20; i++)  
    		fscanf(fp, "%d", &arr[i]);
	    cout << "排序前:";
	    for(int i = 1; i <= 20; i++)  
	    	cout << arr[i] << " ";
	    cout << endl << "排序后:"; 
	    //冒泡排序
	    BubbleSort(arr, 20); 
	    //快速排序
	   QuickSort(arr, 1, 20);
		for(int i = 1; i <= 20; i++)  
			cout << arr[i] << " ";
	    cout << endl << endl; 
    }
	return 0;
} 
/*-----冒泡排序-----*/
void BubbleSort(int arr[], int n) {
    for(int i = 1; i < n; i++) {
    	int flag = 0;  
		//交换标志,如果存在一趟排序没有出现任何交换,则说明序列已经有序,排序结束 
    	for(int j = n; j > i; j--) {
    		if(arr[j] < arr[j-1]) { //某元素小于其前趋值,则交换位置 
    			int temp = arr[j];
				arr[j] = arr[j-1];
				arr[j-1] = temp; 
				flag = 1;  //该趟排序中出现了位置交换 
    		} 	
		}
		if(flag == 0) 
    			return ;
	}
}

冒泡排序
空间复杂度
使用常数个辅助单元,空间复杂度为O(1)
时间复杂度
最好情况:初始序列已经有序,遍历一遍序列,比较了 n-1 次,没有进行交换,时间复杂度为O(n)
最坏情况:初始序列为逆序序列,对于第 i 趟排序,都是将数组的最后一个元素放到数组的第 i 个位置,比较次数为 n-i 次。n-1 趟排序一共比较了∑ (n-i) = n*(n-1)/2 次,时间复杂度为O(n²)
平均情况:时间复杂度为O(n²)
稳定性
该算法从后往前找大于(或小于)的位置,不存在相同元素之间位置交换,因此是稳定

/*-----快速排序-----*/
int Partition(int arr[], int low, int high); //函数声明 

void QuickSort(int arr[], int low, int high) {
    if(low < high) {
    	int pivot = Partition(arr, low, high);  //pivot指针指向分割点的数组下标 
    	QuickSort(arr, low, pivot-1);  //递归排序左子序列 
    	QuickSort(arr, pivot+1, high); //递归排序右子序列 
	}
}

int Partition(int arr[], int low, int high) {
	/*用数组的第一个元素 arr[low]将整个序列分成左右两个子序列
	左子序列中所有值比 arr[low]小
	右子序列中所有值比 arr[low]大 */ 
	int pos = arr[low]; //拿出来做基准,并空出位置 
	while(low < high) {
		/*从序列右侧开始,碰到比arr[low]小的放到左侧去*/ 
		while(low < high && arr[high] >= pos)  
			high--;
		arr[low] = arr[high];
		/*转至序列左侧开始,碰到比arr[low]大的放到右侧去*/ 
		while(low < high && arr[low] <= pos)
			low++;
		arr[high] = arr[low];
	} 
	arr[low] = pos; //再把分割点的值放回来 
	return low;  //返回分割点的下标 
}

快速排序
算法思想
基于分治法,每一趟排序用序列的第一个元素(即为pos)将序列分成左右两个子序列,子序列不要求有序,只需要保证左子序列中的所有值比pos小、右子序列中的所有值比pos大 即可。
对左右两个子序列再进行递归快速排序,分割。
空间复杂度
递归算法需要借助递归工作栈来保存信息,容量和递归调用深度一致
最好情况:为log₂(n+1) 取上界
最坏情况:O(n)
平均情况:O(log₂n)
时间复杂度
每趟排序都是将序列分割成左右两个子序列,因此可得到递推公式
T(n) = 2T(n/2) + O(n)
最好情况:每次Partition都平均分成两部分,时间复杂度为O(nlogn)
最坏情况:按照递推公式计算,可得时间复杂度为O(n²)
平均情况:时间复杂度为O(nlogn)
稳定性
左右序列交换过程中,相同元素的相对位置可能会发生改变,因此是不稳定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值