mirror of
https://github.com/Didnelpsun/CS408.git
synced 2026-06-16 15:07:38 +08:00
更新排序
This commit is contained in:
@@ -63,4 +63,22 @@ bool ShellSort(LinearTable table) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 冒泡排序
|
||||
bool BubbleSort(LinearTable table){
|
||||
elem_type temp;
|
||||
// 外循环为排序趟数,一共需要length-1趟
|
||||
for(int i=0;i<table.length-1;i++){
|
||||
// 内循环为排序趟数,i趟比较次数为length-i
|
||||
// 排序完成的序列在后面
|
||||
for(int j=0;j<table.length-1-i;j++){
|
||||
if(table.data[j]>table.data[j+1]){
|
||||
temp = table.data[j];
|
||||
table.data[j] = table.data[j+1];
|
||||
table.data[j+1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -15,3 +15,15 @@ $D.6$
|
||||
解:$A$。对于任意序列进行基于比较的排序,求最少的比较次数应考虑最坏情况。对任意$n$个关键字排序的比较次数至少$\lceil\log_2(n!)\rceil$。将$n=7$代入公式,答案为$13$。上述公式证明如下(仅供有兴趣的同学参考):在基于比较的排序方法中,每次比较两个关键字后,仅出现两种可能的转移。假设整个排序过程至少需要做$t$次比较,则显然会有$2^t$种情况。由于$n$个记录共有$n!$种不同的排列,因而必须有$n!$种不同的比较路径,于是有$2^t\geqslant n!$,即$t\geqslant\log_2(n!)$。考虑到$t$为整数,故为$\lceil\log_2(n!)\rceil$。
|
||||
|
||||
## 插入排序
|
||||
|
||||
**例题** 有些排序算法在每趟排序过程中,都会有一个元素被放置到其最终位置上,()算法不会出现此种情况。
|
||||
|
||||
$A.$希尔排序
|
||||
|
||||
$B.$堆排序
|
||||
|
||||
$C.$冒泡排序
|
||||
|
||||
$D.$快速排序
|
||||
|
||||
解:$A$。希尔排序是组间有序组内无序。
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
希尔排序也是对直接插入排序的优化。直接插入排序对于基本有序的序列排序效果较好,所以就希望序列能尽可能基本有序。从而希尔排序的思想就是先追求表中元素部分有序,然后逐渐逼近全局有序。
|
||||
|
||||
先将整个待排序元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的),分别进行直接插入排序(或者折半插入排序),然后缩小增量重复上述过程,直到增量为$1$。每次对比只对比两个元素进行插入交换。
|
||||
先将整个待排序元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的),分别进行直接插入排序,然后缩小增量重复上述过程,直到增量为$1$。每次对比只对比两个以上的个元素进行插入交换。
|
||||
|
||||
增量序列的选择建议是第一趟选择元素个数的一半,后面不断缩小到原来的一半。
|
||||
|
||||
@@ -85,13 +85,15 @@
|
||||
|
||||
#### 冒泡排序的过程
|
||||
|
||||
从后往前或从前往后两两比较相邻元素的值,若逆序则交换这两个值,如果相等也不交换,直到序列比较完。这个过程是一趟冒泡排序,第$i$趟后第i个元素会已经排序完成。每一趟都会让关键字最小或最大的一个元素到未排序队列的第一个或最后一个。一共需要$n-1$趟排序。
|
||||
从后往前或从前往后两两比较相邻元素的值,若逆序则交换这两个值,如果相等也不交换,直到序列比较完。这个过程是一趟冒泡排序,第$i$趟后第$i$个元素会已经排序完成。每一趟都会让关键字最小或最大的一个元素到未排序队列的第一个或最后一个。一共需要$n-1$趟排序。
|
||||
|
||||
冒泡排序中所产生的有序子序列一定是全局有序的(不同于直接插入排序),也就是说,有序子序列中的所有元素的关键字一定小于或大于无序子序列中所有元素的关键字,这样每趟排序都会将一个元素放置到其最终的位置上。
|
||||
|
||||
#### 冒泡排序的性能
|
||||
|
||||
空间复杂度为$O(1)$。
|
||||
|
||||
最好情况下即本身序列有序,则比较次数是n-1,交换次数是0,从而时间复杂度是$O(n)$。
|
||||
最好情况下即本身序列有序,则比较次数是$n-1$,交换次数是$0$,从而时间复杂度是$O(n)$。
|
||||
|
||||
最坏情况是逆序情况,比较次数和交换次数都是$\dfrac{n(n-1)}{2}$,所以时间复杂度是$O(n^2)$。
|
||||
|
||||
@@ -103,22 +105,22 @@
|
||||
|
||||
### 快速排序
|
||||
|
||||
快速排序在内部排序中的表现确实是最好的。排序过程类似于构建二叉排序树。
|
||||
快速排序在内部排序中的表现确实是最好的。排序过程类似于构建二叉排序树。基于分治法。
|
||||
|
||||
#### 快速排序的过程
|
||||
|
||||
取待排序序列中的某个元素pivot作为基准(一般取第一个元素),通过一趟排序,将待排元素分为左右两个子序列,左子序列元素的关键字均小于或等于基准元素的关键字,右子序列的关键字则大于基准元素的关键字,然后分别对两个子序列继续进行排序,直至整个序列有序。
|
||||
取待排序序列中的某个元素$pivot$作为基准(一般取第一个元素),通过一趟排序,将待排元素分为左右两个子序列,左子序列元素的关键字均小于或等于基准元素的关键字,右子序列的关键字则大于基准元素的关键字,称进行了一趟快速排序(一次划分),然后分别对两个子序列继续进行排序,直至整个序列有序。
|
||||
|
||||
1. 先选择个值做标杆,把标杆放入pivot,比标杆小的放左边,大的放右边。
|
||||
2. 初始时,令high指向序列最右边的值,low指向序列最左边的值。
|
||||
3. 然后从high开始,当遇到比标杆大的值时high--。
|
||||
4. 当遇到比标杆小的值,就取出这个值放入当前low所指的位置。
|
||||
5. 然后high不动,low++开始移动。
|
||||
6. 若low所指向的值比标杆小,low++。
|
||||
7. 若low所指向的值比标杆大,则放入当前high所指向的位置。
|
||||
8. 然后low不动,high--开始移动。回到步骤三开始执行。
|
||||
9. 当low=high时表示low和high之前的元素都比基准小,low和high之后的元素都比基准大,完成了一次划分。然后把基准元素放入low和high指向的位置。
|
||||
10. 不断交替使用low和high指针进行对比。对左右子序列进行同样的递归操作即可,从步骤三开始。若左右两个子序列的元素数量等于一,则无需再划分。
|
||||
1. 先选择个值做标杆,把标杆放入$pivot$,比标杆小的放左边,大的放右边。
|
||||
2. 初始时,令$high$指向序列最右边的值,$low$指向序列最左边的值。
|
||||
3. 然后从$high$开始,当遇到比标杆大的值时$high--$。
|
||||
4. 当遇到比标杆小的值,就取出这个值放入当前$low$所指的位置。
|
||||
5. 然后$high$不动,$low++$开始移动。
|
||||
6. 若$low$所指向的值比标杆小,$low++$。
|
||||
7. 若$low$所指向的值比标杆大,则放入当前$high$所指向的位置。
|
||||
8. 然后$low$不动,$high--$开始移动。回到步骤三开始执行。
|
||||
9. 当$low=high$时表示$low$和$high$之前的元素都比基准小,$low$和$high$之后的元素都比基准大,完成了一次划分。然后把基准元素放入$low$和$high$指向的位置。
|
||||
10. 不断交替使用$low$和$high$指针进行对比。对左右子序列进行同样的递归操作即可,从步骤三开始。若左右两个子序列的元素数量等于一,则无需再划分。
|
||||
|
||||
#### 快速排序的性能
|
||||
|
||||
|
||||
Reference in New Issue
Block a user