1. 冒泡排序
a. 基本思想
假设待排序比表长为n, 从后向前(或从前往后)两两比较相邻元素的值,若未逆序则交换,直到序列比较完,则称一趟冒泡。最小值如同气泡逐渐向上“漂浮”,直至“水面”。下一趟最小元素已到第一序列,不用比较。待排序列减少一个元素,每趟冒泡都将序列中的最小元素放到序列的最终位置
b. 代码
void BubbleSort(ElemType A[], int n){
//用冒泡法将序列A中的元素按从小到大排列
for(i=0;i<n-1;i++){
flag = false; //表示本趟冒泡是否发生交换的标志
for(j=n-1;j>i;j--) //一趟冒泡过程
if(A[j-1].key>A[j].key){ //若为逆序
swap(A[j-1],A[j]);
flag = ture;
}
if(flag == false)
return ; //本次遍历后没有发生交换,说明表有序。
}
}
这时flag标志的使用,在最优情况下,O(1)即可排序完
c. 性能评估
空间效率O(1)。时间效率O(n^2)。稳定性:由A[j-1].key>A[j].key可以看出,即使相同也不会交换,从而冒泡排序是稳定的排序方法。
2. 快速排序
a. 基本思想
快速排序是对冒泡排序的一种改进。基本思想就是分冶法,在待排序表L[1…….n]中任取一个元素pivot作为基准(一般选第一位元素),通过一趟排序将待排序表划分成独立的2个部分L[1…..k-1]和L[k+1…..n]。使得L[1…..k-1]中的所有元素小于pivot,L[k+1……n]都大于或等于pivot。则pivot最终放在位置L[k]上,这称为一趟快速排序。而后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在其最终位置上。
b. 代码
void QuickSort(ElemType A[], int low, int high){
if(low<high){ //递归跳出的条件
int pivotpos = Partition(A,low,high); //划分
QuickSort(A,low,pivotpos-1); //对左表递归排序
QuickSort(A,pivotpos+1,high);
}
}
int Partition(ElemType A[],int low,int high) {
//严版教材中的划分算法(一趟排序过程)
ElemType pivot = A[low]; //将当前表中第一个元素设为枢轴值,对表进行划分
while(low<high){ //循环跳出条件
while(low<high&&A[high]>=pivot) --high;
A[low] = A[high]; //将比枢轴值小的元素移动到左端
while(low<high&&A[low]<=pivot) ++low;
A[high] = A[low]; //将比枢轴值大的元素移动到右端
}
A[low] = pivot; //枢轴元素存放到最终位置
return low; //返回存放枢轴的最终位置
}
手写过程(只写一趟比较)
pviot | 比较 | 数组 |
---|---|---|
null | null | 6(low) 7 10 2 4(high) |
6 | 4<6 | 4 7(low) 9 10 2 4(high) |
6 | 7>6 | 4 7(low) 9 10 2 7(high) |
6 | 2<6 | 4 2(low) 9 10 2(high) 7 |
6 | 9>6 | 4 2 9(low) 10 9(high) 7 |
6 | 10>6 | 4 2 9(low high) 10 9 7 |
6 | low=high | 4 2 6 10 9 7 |
c. 性能分析
空间效率:由于快排是递归的,需要借助一个递归工作栈来保存每一层递归调用的必要信息。O(n)。最坏时间复杂度O(n^2)。
不稳定的排序方法。