1. 冒泡排序
算法思想:不停地比较相邻的记录,如果不满足排序要求,就交换相邻记录,直到所有记录都已经排好序
检查每次冒泡过程中是否已经发生过交换,如果没有,则表明整个数组已经排好序了,排序结束。
/*冒泡排序*/
template <class Record>
void BubbleSort(Record Array[], int n){
bool NoSwap; //是否发生了交换的标志
int i, j;
for (i = 0; i < n; i++){
NoSwap = true; //标志初始为真
for (j = n - 1; j > i;j--)
if (Array[j] < Array[j - 1]){ //判断是否逆置
swap(Array, j, j - 1); //交换逆置对
NoSwap = false; //发生了交换,标志变为假
}
if (NoSwap) //没有发生交换,则已完成排好排序
return;
}
}
算法分析:
- 稳定
- 空间代价:O(1)
- 时间代价分析:比较次数:最少O(n)、最多:n(n-1)/2=O(n^2)
- 时间代价结论:最大,平均时间代价均为O(n^2)、最小时间代价为O(n),最佳情况下只运行第一轮循环。
2. 快速排序
算法思想:
- 选择轴值
- 将序列划分为两个子序列L和R,使得L中所有记录都小于或等于轴值,R中记录都大于轴值。
- 对于序列L和R递归进行快速排序
分治策略的基本思想:
分治策略的实例:
- BST查找、插入、删除算法
- 快速排序、归并排序
- 二分检索
主要思想:
- 划分
- 求解子问题
- 综合解
轴值选择:
- 尽可能使L,R长度相等
- 选择策略:(1)选择最左边记录(2)随机选择(3)选择平均值
一次分割过程:
- 选择轴值并存储轴值
- 最后一个元素放到轴值位置
- 初始化下标i,j,分别指向头尾
- i递增直到遇到比轴值大的元素,并将元素覆盖到j的位置;j递减直到遇到比轴值小的元素,将此元素覆盖到i的位置。
- 重复上一步直到i==j,将轴值放到i的位置。
/*快速排序算法*/
template <class Record>
void QuickSort(Record Array[], int left, int right){
//Array[]为待排序数组,left,right分别为数组两端
if (right <= left) //只有0或1个记录,就不需排序
return;
int pivot = SelectPivot(left, right); //选择轴值
swap(Array, pivot, right); //轴值放在数组末端
pivot = Partition(Array, left, right); //分割后轴值正确
QuickSort(Array, left, pivot - 1); //左子序列递归快排
QuickSort(Array, pivot + 1, right); //右子序列递归快排
}
int SelectPivot(int left, int right){
//选择轴值,参数left,right分别表示序列的左右段端下标
return (left + right) / 2;
}
template <class Record>
int Partition(Record Array[], int left, int right){
//分割函数,分割后轴值已到达正确位置
int l = left; //l为左指针
int r = right; //r为右指针
Record TempRecord = Array[r]; //保存轴值
while (l != r){ //l和r不断向中间移动,直到相遇
//l指针向右移动,直到找到一个大于轴值的记录
while (Array[l] <= TempRecord&&r > l)
l++;
if (l < r){ //未相遇,将逆置元素换到右边空位
Array[r] = Array[l];
r--; //r指针向左移动一步
}
//r指针向左移动,直到找到一个小于轴值的记录
while (Array[r] >= TempRecord&&r>l)
r--;
if (l < r){ //未相遇,将逆置元素换到左空位
Array[l] = Array[r];
l++; //l指针向右移动一步
}
} //end while
Array[l] = TempRecord;//把轴值回填到分界位置l上
return l; //返回分界位置l
}
时间代价:
- 长度为n的序列,时间为T(n) T(0)=T(1=1
- 选择轴值时间为常数
- 分割时间为cn
- 分割后长度分别为i和n-i-1
- 左右子序列T(i)和T(n-i-1)
- 总的时间代价:O(n)
算法分析:
- 最差情况:时间代价:O(n^2)、空间代价:O(n)
- 最佳情况:时间代价:O(nlogn)、空间代价:O(log n)
- 平均代价:时间代价:O(n log n)、空间代价:O(log n)