计算机算法设计与分析——排序(递归算法)
1. 简单选择排序
基本思想:每一趟在n-i+1(i=1,2,…,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。具体来说,假设长度为n的数组arr,要按照从小到大排序,那么先从n个数字中找到最小值min1,如果最小值min1的位置不在数组的最左端(也就是min1不等于arr[0]),则将最小值min1和arr[0]交换,接着在剩下的n-1个数字中找到最小值min2,如果最小值min2不等于arr[1],则交换这两个数字,依次类推,直到数组arr有序排列。算法的时间复杂度为O(n^2)。
void SelectSort(int a[], int n, int i) { int j, k; if (i == n - 1) //表示已经选择到最后一个值,无序排序 { return; } else { k = i; //k记录a[i..n-1]中最小元素的下标 for (j = i + 1; j<n; j++) //在a[i..n-1]中找出最小元素 { if (a[j] < a[k]) { k = j; } } if (k != i) //若最小元素不是a[i] { swap(a[i], a[k]); //交换 } SelectSort(a, n, i + 1); } }
百度百科:简单选择排序
2.冒泡排序
基本思想:首先从数组的第一个元素开始到数组最后一个元素为止,对数组中相邻的两个元素进行比较,如果位于数组左端的元素大于数组右端的元素,则交换这两个元素在数组中的位置,此时数组最右端的元素即为该数组中所有元素的最大值。接着对该数组剩下的n-1个元素进行冒泡排序,直到整个数组有序排列。
f(a,n,i)=不做任何事情,算法结束 当i=n-1
f(a,n,i)=对a[i…n-1]元素序列,从a[n-1]开始
进行相邻元素比较; 否则
若相邻两元素反序则将两者交换;
若没有交换则返回,否则执行f(a,n,i+1);
// 冒泡排序 void BubbleSort(int a[], int n, int i) { int j; bool exchange; if (i == n - 1) //满足递归出口条件 { return; } else { exchange = false; //置exchange为false for (j = n - 1; j > 1; j--) { if (a[j] < a[j - 1]) //当相邻元素反序时 { swap(a[j], a[j - 1]); exchange = true; //发生交换置exchange为true } } if (exchange == false) //未发生交换时直接返回 { return; } else //发生交换时继续递归调用 { BubbleSort(a, n, i + 1); } } }
百度百科:冒泡排序
3.快速排序
基本思想:①先从数列中取出一个数作为基准数。②分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。③再对左右区间重复第二步,直到各区间只有一个数。
void QuickSort(int a[], int s, int t)//对a[s..t]元素序列进行递增排序 { if (s < t)//序列内至少存在2个元素的情况 { int i = Partition(a, s, t); QuickSort(a, s, i - 1);//对左子序列递归排序 QuickSort(a, i + 1, t);//对右子序列递归排序 } }
// 快速排序 void Partition(int a[], int left, int right)//划分算法 { int i = left; int j = right; int key = a[left];//用序列的第1个记录作为基准 while (i != j)//从序列两端交替向中间扫描,直至i=j为止 { while (j > i&&a[j] >= key) { j--;//从右向左扫描,找到第1个关键字小于tmp的a[j] } a[i] = a[j];//将a[j]前移到a[i]的位置 while (i < j&&a[i] <= key) { i++;//从左往右扫描,找到第1个关键字大于tmp的a[i] } a[j] = a[i];//将a[i]后移到a[j]的位置 } a[i] = key; }
百度百科:快速排序
4.自底向上的归并排序
基本思想:数组中先一个一个归并成两两有序的序列,两两有序的序列归并成四个四个有序的序列,然后四个四个有序的序列归并八个八个有序的序列,以此类推,直到,归并的长度大于整个数组的长度,此时整个数组有序。需要注意的是数组按照归并长度划分,最后一个子数组可能不满足长度要求,这个情况需要特殊处理。
void MergePass(int a[],int length,int n) //一趟二路归并排序 { int i; for (i = 0; i + 2 * length - 1 < n; i = i + 2 * length) //归并length长的两相邻子表 Merge(a, i, i + length - 1, i + 2 * length - 1); if (i + length - 1 < n) //余下两个子表,后者长度小于length Merge(a, i, i + length - 1, n - 1); //归并这两个子表 } void Merge(int a[], int low, int mid, int high) //a[low..mid]和a[mid+1..high]->a[low..high] { int *tmpa; int i = low, j = mid + 1, k = 0; tmpa = (int *)malloc((high - low + 1)*sizeof(int)); while (i <= mid&&j <= high) if (a[i] <= a[j]) //将第1子表中的元素放入tmpa中 { tmpa[k] = a[i]; i++; k++; } else //将第2子表中的元素放入tmpa中 { tmpa[k] = a[j]; j++; k++; } while (i <= mid) //将第1子表余下部分复制到tmpa { tmpa[k] = a[i]; i++; k++; } while (j <= high) //将第2子表余下部分复制到tmpa { tmpa[k] = a[j]; j++; k++; } for (k = 0, i = low; i <= high; k++, i++) //将tmpa复制回a中 a[i] = tmpa[k]; free(tmpa); //释放tmpa所占内存空间 } void MergeSort(int a[], int n) //二路归并算法 { int length; for (length = 1; length < n; length = 2 * length) MergePass(a, length, n); }
百度百科:归并排序
- 点赞
- 收藏
- 分享
- 文章举报
- 回过头再看 计算机体系结构6----编译器指令重排序--导致并发执行出现问题
- 快排序的递归算法
- 机试:成绩排序(2000年清华大学计算机研究生机试真题)
- 计算机算法之快速排序、原址排序、递归的最好应用
- 计算机考研之数据结构-排序
- 算法设计与分析——普通高校本科计算机专业特色教材精选
- 回过头再看 计算机体系结构6----编译器指令重排序--导致并发执行出现问题
- 分治与递归:归并排序的递归算法
- 一道递归算法--String[] 里面的字符无重复的排序
- 合并排序的递归算法
- 插入排序的递归算法(升序)
- 2008秋-计算机软件基础-多关键字排序
- 多种方法实现。递归算法和标准函数库(STL)实现全排列+sort在全排列前的排序
- 算法设计与分析:第二章 递归 2.1计数排序之统计数对
- 插入排序、归并排序和递归算法的复杂性分析
- 计算机算法设计与分析——求解查找问题
- 算法提高 选择排序( 递归算法)
- 快速排序的递归算法
- 计算机算法设计与分析——求解棋盘覆盖问题
- 牛客网计算机复试上机习题之成绩排序