对接近有序的数组排序

给定一个数组,数组内每一个元素的位置和其最终排序好的位置 的 距离相差在 k 以内,怎么有效的对其排序?要求时间复杂度为 O(n log k)



#include<iostream>
using namespace std;
void swap(int *x, int *y);

//小顶堆类
class MinHeap
{
	int *harr; // 堆中的元素数组
	int heap_size; // 堆的大小
public:
	// 构造函数
	MinHeap(int a[], int size); 

	// 从给定的下标开始调整堆
	void MinHeapify(int);

	//i的左孩子的下标
	int left(int i) { return (2 * i + 1); }

	// i的右孩子的下标
	int right(int i) { return (2 * i + 2); }

	//取走最小值(或者说是 root), 并添加新的元素x
	int replaceMin(int x);

	// 取最小值
	int extractMin();
};

// k为每个元素的当前位置和排序数组位置相差的范围
int sortK(int arr[], int n, int k)
{
	// 用前 (k+1) 个元素创建最小堆
	int *harr = new int[k + 1];
	for (int i = 0; i <= k && i<n; i++) // i < n 防止 k>n的情况
		harr[i] = arr[i];
	MinHeap hp(harr, k + 1);

	for (int i = k + 1, ti = 0; ti < n; i++, ti++)
	{
		//如果有剩余元素,就替换掉堆顶
		if (i < n)
			arr[ti] = hp.replaceMin(arr[i]);
		// 否则就依次取走堆顶的元素,
		else
			arr[ti] = hp.extractMin();
	}

	return 0;
}

// 以下是标准的小顶堆的实现
MinHeap::MinHeap(int a[], int size)
{
	heap_size = size;
	harr = a;
	int i = (heap_size - 1) / 2;
	while (i >= 0)
	{
		MinHeapify(i);//构建初始堆
		i--;
	}
}

//从小顶堆中移除堆顶元素
int MinHeap::extractMin()
{
	int root = harr[0];
	if (heap_size > 1)
	{
		harr[0] = harr[heap_size - 1];
		heap_size--;
		MinHeapify(0);
	}
	return root;
}

// 替换root和给定的x
int MinHeap::replaceMin(int x)
{
	int root = harr[0];
	harr[0] = x;
	if (root < x)
		MinHeapify(0);
	return root;
}

// 调整小顶堆(递归的方法)
void MinHeap::MinHeapify(int i)
{
	int l = left(i);
	int r = right(i);
	int smallest = i;
	if (l < heap_size && harr[l] < harr[i])
		smallest = l;
	if (r < heap_size && harr[r] < harr[smallest])
		smallest = r;
	if (smallest != i)
	{
		swap(&harr[i], &harr[smallest]);
		MinHeapify(smallest);
	}
}

// 交换
void swap(int *x, int *y)
{
	int temp = *x;
	*x = *y;
	*y = temp;
}

//打印数组
void printArray(int arr[], int size)
{
	for (int i = 0; i < size; i++)
		cout << arr[i] << " ";
	cout << endl;
}

// 测试
int main()
{
	int k = 3;
	int arr[] = { 2, 6, 3, 12, 56, 8 };
	int n = sizeof(arr) / sizeof(arr[0]);
	sortK(arr, n, k);

	cout << "Following is sorted array\n";
	printArray(arr, n);

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值