常见查找-排序算法C++实现

//
// 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)归并排序
 */

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值