chapter 9 排序&查找
- 大学C语言程序设计
- chapter 9 排序&查找
- 1. 排序认识
- 2. 冒泡排序
- 3. 选择排序
- 4. 插入排序
- 5. 快速排序
- 6. 归并排序
- 7. 计数排序
- 8. 顺序查找
- 9. 二分查找
- chapter 9 排序&查找
大学C语言程序设计
chapter 9 排序&查找
1. 排序认识
排序是指:将一个无序数列,经过一些处理,变成一个有序数列(非降序列/非增序列)的过程。
也可以形象化描述为:对于任意 i
当对于任意 i 当对于任意 i 稳定排序:对于 i 而对于排序的方法按照基本原理主要分两种: 基于比较的排序方法:冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序、希尔排序。 非基于比较的排序方法:计数排序、基数排序、桶排序。 它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 冒泡排序算法的运作如下:(从后往前) 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 3.针对所有的元素重复以上的步骤,除了最后一个。 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。 初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列; 每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。 一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下: ⒈ 从第一个元素开始,该元素可以认为已经被排序 ⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描 ⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置 ⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置 ⒌ 将新元素插入到下一位置中 ⒍ 重复步骤2 速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。 它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。 该方法的基本思想是: 1.先从数列中取出一个数作为基准数。 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。 3.再对左右区间重复第二步,直到各区间只有一个数。 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法。 该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 将已有序的子序列合并,得到完全有序的序列; 即先使每个子序列有序,再使子序列段间有序。 若将两个有序表合并成一个有序表,称为二路归并。 归并排序是一种稳定的排序方法。 对各个元素出现次数进行计数,最后依次输出。(桶距为 1 时的桶排序) 通过遍历无序数组,一个一个对比数组中的值与目标值是否相同。 二分查找是基于一个有序序列而言,所以在使用二分查找前需要对该序列排序处理。 二分查找,又称折半查找,基本思想是将 n 个元素分成大致相等的两部分,取a[n/2] 与 x 做比较,如果 x=a[n/2],则找到 x,算法中止;
2. 冒泡排序
//冒泡排序:最大的下沉到最后,小的向上冒泡
void BubbleSort(int arr[], int l, int r){
for(int i=r; i>=l; i--){
for(int j=l; ja[j+1]) {
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
3. 选择排序
然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。
以此类推,直到所有元素均排序完毕。//选择排序:每次选择最大的放在最后
void SelectSort(int a[], int l, int r){
for(int i=r; i>=l; i--){
int maxi=i;
for(int j=l; j
4. 插入排序
//插入排序:向左边有序序列中插入一个元素
void InsertSort(int a[], int l, int r){
for(int i=l; i<=r; i++){
int k=i;
for(int j=i; j>=l; j--){
if(a[k]
5. 快速排序
//快速排序:取一个基准值,大的放右边,小的放左边
void QuickSort(int a[], int l, int r){
if(l>=r) return;
int i=l, j=r, mid=a[l];
while(i
6. 归并排序
//归并排序:分治思想,将数据递归均分成两部分,直到数据元素个数为1,在回溯合并
void merge(int a[], int l, int mid, int r);
void MergeSort(int a[], int l, int r){
if(l>=r) return;
int mid=(l+r)/2;
MergeSort(a, l, mid);
MergeSort(a, mid+1, r);
merge(a, l, mid, r);
}
//合并:两个有序序列合并,需要开一个临时空间 temp[]
void merge(int a[], int l, int mid, int r){
int i=l, j=mid+1, cnt=0;
while(i<=mid && j<=r){
if(a[i]
7. 计数排序
#include
8. 顺序查找
对于数据没有任何要求,但是时间复杂度 O(n).9. 二分查找
如果 xa[n/2],则只要在数组a的右半部搜索 x。int binSearch(int arr[], int l, int r, int x){
while(l<=r){
int mid = (l+r)/2;
if(x < arr[mid]) r=mid-1;
else if(x > arr[mid]) l=mid+1;
else if(x == arr[mid]) return mid;
}
return 0;
}