这里的测试数据来自于之前自己随便写的生成器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)
稳定性
左右序列交换过程中,相同元素的相对位置可能会发生改变,因此是不稳定的