//
// Created by Jiwen-LI on 2020/8/22.
//
/***************************************************************************
查找算法
***************************************************************************/
//二分法查找
int BinarySearch(int a[],int val,int n)
{
int low = 0,high = n -1,mid;
while (low<= high) {
mid = low + (low +high)/2; //取区间中点
if (a[mid] == val) //查找成功
return mid;
else if (a[mid] > val) //在左区间中查找
high = mid - 1;
else //在右区间中查找
low = mid + 1;
}
return -1; //查找失败
}
/***************************************************************************
排序算法
***************************************************************************/
/**********************************************
A. 插入排序算法
************************************************/
/*
* (1) 直接插入排序
*/
void DirectInsertSort(int A[],int n)
{
int i,j;
for (int i = 2; i <= n; ++i) {
//如果待插入元素比有序序列的最后一个还大,则不用插入,直接放在原位置
if (A[i] < A[i - 1]) {
A[0] = A[i]; //设置监哨岗
for (j = i - 1; A[0] < A[j]; --j) //边寻找插入位置边移动元素
A[j + 1] = A[j]; //退出循环时j+1为待插入元素的位置
A[j + 1] = A[0]; //复制到插入位置
}
}
}
/*
void DirectInsertSort(int A[],int n)
{
int i,j,k;
for (int i = 2; i <= n; ++i) {
A[0] = A[i]; //设置监哨岗
for (j = i - 1; A[0] < A[j]; --j) //寻找A[i]插入位置,退出循环时j+1为待插入元素的位置
for (k = i - 1; k > j; --k)
A[k + 1] = A[k]; //元素后移
A[j + 1] = A[0];
}
}
*/
/*
* (2)二分/折半插入排序
*/
void BinaryInsertSort(int A[],int n)
{
int i,j,low,high,mid;
//记录的是待插入的元素的下标,也就是说i-1之前的元素都是有序的
for (i = 2; i <=n; ++i) {
A[0] = A[i]; //保存待插入的值
low = 1;high = i -1;
while (low <= high) { //折半查找
mid = low + (high - low)/2;
if(A[mid] > A[0])
high = mid - 1;
else
low = mid + 1;
} //循环结束,low为插入位置,low = high + 1
//找到了待插入的位置,接下来从后往前依次后移元素腾出位置
for (j = i - 1; j >= low; --j) // for (j = i - 1; j >= high + 1; --j)
A[j + 1] = A[j];
A[low] = A[0]; // A[high + 1] = A[0]
}
}
/*
* (3)希尔排序
*/
//步长为d的一趟希尔排序,对比可知,直接插入排序是d = 1时的一趟希尔排序
void ShellInsert(int A[], int n, int d)
{
int i,j;
for (i = d + 1; i <= n; ++i) {
if (A[i] < A[i - d]) {
A[0] = A[i]; //设置监哨岗
for (j = i - d; A[0] < A[j] && j > 0; j = j - d) //边寻找插入位置边移动元素
A[j + d] = A[j]; //退出循环时j+d为待插入元素的位置
A[j + d] = A[0]; //复制到插入位置
}
}
}
//确定步长序列dt[],循环调用ShellInsert
void ShellSort(int A[],int n, int dt[],int t)
{ //dt[]为步长序列,t为步长序列的长度
for (int k = 0; k < t - 1; k ++)
ShellInsert(A,n,dt[k]);
}
/**********************************************
B. 交换排序算法
************************************************/
/*
* (1) 冒泡排序,从后往前(GET),小的向左冒泡,大的往右沉
*/
void BubbleSort(vector<int> &A, int n)
{ //最多进行n - 1趟排序
for (int i = 1; i <= n - 1; ++i) {
int flag = 0; //是否发生交换的标志
for (int j = n; j >= i; --j) { //第i趟前i个已经有序
if (A[j] < A[j - 1]) { //如果前面元素比后面元素大则交换
swap (A[j], A[j - 1]);
flag = 1; //发生了交换
}
}
if (!flag) //如果某一趟排序没有交换,则说明已经有序
break; //return;
}
}
/*
* (2) 快速排序
*/
int Partition(int A[], int low, int high)
{
int pivot = A[low]; //第一个元素作为枢纽
while (low < high) {
while (low < high && A[high] >= pivot) --high; //从末尾找到第一个比枢轴小的元素
A[low] = A[high]; //用high的元素替换low的元素
while (low < high && A[low] <= pivot) ++low; //再从开头找到第一个比枢轴小大的元素
A[high] = A[low]; //用low的元素替换high的元素
}
A[low] = pivot; //枢纽元素存放到最终位置
return low; //返回存放枢纽的最终位置
}
void QuickSort(int A[], int low, int high)
{
if (low < high) { //if (low >= high) return;
int pivotPos = Partition(A,low,high);
QuickSort(A, low, pivotPos - 1); //分治递归左半部分
QuickSort(A, pivotPos + 1, high); //分治递归右半部分
}
}
/**********************************************
C. 选择排序算法
************************************************/
/*
* (1) 简单选择排序
*/
void SimpleSelectSort(vector<int> A)
{
int n = A.size();
int min; // min存放的是当前无序序列中最小元素所在下标,初始设置为第i个元素
for (int i = 0; i < n - 1; i++) { // 最多n-1趟排序,最后一个元素不需要排序
for (int j = i + 1; j < n; j++) {
if (A[j] < A[min]) { // 如果这个值更小,则更新min值为这个更小值的下标
min = j;
}
}
if (min != i) { // 如果第i个元素不是当前无序序列最小的,则和最小的进行交换
swap(A[min], A[i]);
}
}
}
/*
* (2)堆排序
*/
//大顶堆,调整堆
//A为存储堆的数组,len为数组长度(堆中元素个数),k为待检查的节点下标
void AdjustHeap(int A[], int len, int k)
{
A[0] = A[k];
for (int i = 2 * k; i <= len; i *= 2) { //从当前节点的左孩子开始往下比较
if (i < len && A[i] < A[i + 1]) //如果当前节点有右孩子且比左孩子大
++i; //则考虑将当前节点和右孩子比较
if (A[0] < A[i]) { //当前节点k和最大的孩子节点i比较
A[k] = A[i];
k = i; //从i开始继续往下检查,直到所有节点检查完毕
}
else
break;
}
A[k] = A[0]; //检查到最后的k 值就是最后一轮交换过的节点位置下标
}
//堆排序算法的实现
void BuildMaxHeap(int A[], int len)
{
for (int i = len/2; i > 0; --i) //建立初始堆
AdjustHeap(A,len,i);
for (int i = n; i >= 2; --i) { //n - 1次筛选
swap(A[1],A[i]); //堆中最后一个元素替代堆顶位置,A[1] = A[i]
AdjustHeap(A,i - 1, 1); //堆中元素个数逐减,为i - 1
}
}
/*
* (3)归并排序
*/
常见查找-排序算法C++实现
于 2020-08-24 16:02:17 首次发布