一、冒泡排序
基本思想:每趟不断将记录两两比较,并按“前小后大”规则交换
算法:
void bubble_sort(SqList &L){ //冒泡排序算法
int m,i,j; RedType x; //交换时临时存储
for(m=1;m<=n-1;m++){ //总共需m趟
for(j=1;j
x=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=x; //交换
}
}
}
优点:每趟结束时,不仅能挤出一个最大值到最后面位置,还能同时部分理顺其他元素
提高效率:一旦某一趟比较时不出现记录交换,说明已排好序,就可以结束算法
改进的冒泡排序算法:
void bubble_sort(SqList &L){ //改进的冒泡排序算法
int m,i,j; flag=1;RedType x; //flag作为是否有交换的标记
for(m=1;m<=n-1 && flag==1;m++){
flag=0;
for(j=1;j
flag=1; //发生交换,flag置为1,若本趟没发生交换,flag保持为0
x=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=x; //交换
}
}
}
时间复杂度
①最好情况(正序)
比较次数:n-1
移动次数:0
②最坏情况(逆序)
比较次数:n(n-1)/2
移动次数:3n(n-1)/2
二、快速排序
基本思想:任取一个元素为中心(pivot),所有比它小的元素一律前放,比它大的元素一律后放,形成左右两个子表,对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个
通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录进行排序,以达到整个序列有序:
①每一趟的子表的形成是采用从两头向中间交替式逼近法
②由于每趟中对各子表的操作都相似,可采用递归算法
算法:
void main(){
QSort(L,1,L.length);}
void QSort(SqList &L, int low, int high){ //对顺序表L快速排序
if(low
//将L.r[low..high]一分为二,pivotloc为枢轴元素排好序的位置
QSort(L,low,pivotloc-1); //对低子表递归排序
QSort(L,pivotloc+1,high); //对高子表递归排序
}
}
int Partition(SqList &L,int low, int high){
L.r[0]=L.r[low]; pivotkey=L.r[low].key;
while(low
L.r[low]=L.r[high];
while(low
L.r[high]=L.r[low];
}
L.r[low]=L.r[0];
return low;
}
时间复杂度:平均计算时间是O(nlog2n)
空间复杂度:快速排序不是原地排序,由于程序中使用了递归,需要递归调用栈的支持,而栈的长度取决于递归调用的深度,在平均情况下需要O(logn)的栈空间,最坏情况下,栈空间可达O(n)
快速排序不适于对原本有序或基本有序的记录序列进行排序
快速排序算法分析:
①划分元素的选取是影响时间性能的关键
②输入数据次序越乱,所选划分元素值的随机性越好,排序速度越快,快速排序不是自然排序方法
③改变划分元素的选取方法,至多只能改变算法平均情况下的时间性能,无法改变最坏情况下的时间性能
