归并/堆排/快排/二分---C++实现

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <list>

using namespace std;

int binSearch(vector<int>arr,int start,int end,int key)
{
	int ret = -1;
	int mid = start + ((end-start)>>1);
	for(int a : arr)
	{
		if(key>a)
		{
			start = mid+1;
		}
		else if(key<a)
		{
			end = mid-1;
		}
		else
			ret = mid;
	}

	return ret;
}


void sift_down(int arr[], int start, int end) {
  // 建立父结点指标和子结点指标
  int dad = start;
  int son = dad * 2 + 1;
  while (son <= end) {  // 子结点指标在范围内才做比较
    if (son + 1 <= end && arr[son] < arr[son + 1])  // 先比较两个子结点大小,选择最大的
      son++;
    if (arr[dad] >= arr[son])  // 如果父结点比子结点大,代表调整完毕,直接跳出函数
      return;
    else {  // 否则交换父子内容,子结点再和孙结点比较
      swap(arr[dad], arr[son]);
      dad = son;
      son = dad * 2 + 1;
    }
  }
}

void heap_sort(int arr[], int len) {
  // 从最后一个节点的父节点开始sift down以完成堆化(heapify)
  for (int i = (len - 1 - 1) / 2; i >= 0; i--) sift_down(arr, i, len - 1);
  // 先将第一个元素和已经排好的元素前一位做交换,再重新调整(刚调整的元素之前的元素),直到排序完毕
  for (int i = len - 1; i > 0; i--) {
    swap(arr[0], arr[i]);
    sift_down(arr, 0, i - 1);
  }
}

// 模板的T参数表示元素的类型,此类型需要定义小于(<)运算
template <typename T>
// arr为需要被排序的数组,len为数组长度
void quick_sort(T arr[], const int len) {
  if (len <= 1) return;
  // 随机选择基准(pivot)
  const T pivot = arr[rand() % len];
  // i:当前操作的元素
  // j:第一个等于pivot的元素
  // k:第一个大于pivot的元素
  int i = 0, j = 0, k = len;
  // 完成一趟三路快排,将序列分为:小于pivot的元素 | 等于pivot的元素 |
  // 大于pivot的元素
  while (i < k) {
    if (arr[i] < pivot)
      swap(arr[i++], arr[j++]);
    else if (pivot < arr[i])
      swap(arr[i], arr[--k]);
    else
      i++;
  }
  // 递归完成对于两个子序列的快速排序
  quick_sort(arr, j);
  quick_sort(arr + k, len - k);
}

// 假设数组的大小是n+1,冒泡排序从数组下标1开始
void bubble_sort(int a[], int n) {
  bool flag = true;
  while (flag) {
    flag = false;
    for (int i = 1; i < n; ++i) {
      if (a[i] < a[i - 1]) {
        flag = true;
        int t = a[i];
        a[i] = a[i - 1];
        a[i - 1] = t;
      }
    }
  }
}

void merge(int a[],int t[],int ll, int rr) {
  // 用来把 a[ll.. rr - 1] 这一区间的数排序。 t 数组是临时存放有序的版本用的。
	
  if (rr - ll <= 1) return;
  int mid = ll + (rr - ll >> 1);
  merge(a,t,ll, mid);
  merge(a,t,mid, rr);
  int p = ll, q = mid, s = ll;
  while (s < rr) {
    if (p >= mid || (q < rr && a[p] > a[q])) {
      t[s++] = a[q++];
      // ans += mid - p;  求逆序对个数
    } else
      t[s++] = a[p++];
  }
  for (int i = ll; i < rr; ++i) a[i] = t[i];
}
//关键点在于一次性创建数组,避免在每次递归调用时创建,以避免对象的无谓构造和析构。


int main()
{
	int arr[10] = {123,523,53,151,4,134,1,2431,234,14};
	int t[10] = {0};
	merge(arr,t,0,10);
	for(auto a : arr)
	{
		cout<<a<<" ";
	}




	//int arr[6] = {1,4,5,7,8,9};
	//vector<int> arr1(arr,arr+6);
	//if(binSearch(arr1,0,6,8))
	//{
	//	cout<<"OK"<<endl;
	//}

	while(1);
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SS_zico

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值