数据结构 堆的c语言实现 TopK问题

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* _a;
	int _size;
	int _capacity; 
}Heap;

1、交换数据

void Swap(int* a, int* b)
{
   int x = *a;
   *a = *b;
   *b = x;
}

2、向下调整算法(建小堆)

// 小堆
// 前提条件:左右子树都是堆
void AdjustDown(HpDataType* a, size_t n, int root)
{
   int parent = root;
   int child = parent * 2 + 1;
   while (child < n)
   {
      // 找出小的那个孩子
      if (child + 1 < n && a[child+1] < a[child])
      {
         ++child;
      }
      // 1、孩子比父亲小,则交换,继续往下调
      // 2、孩子比父亲大,则终止调整
      if (a[parent] > a[child])
      {
         Swap(&a[child], &a[parent]);
         parent = child;
         child = parent * 2 + 1;
      }
      else
      {
         break;
      }
   }
}

3、堆的构建(小堆)

void HeapCreate(Heap* hp, HpDataType* a, size_t n)
{
   hp->_a = (HpDataType*)malloc(sizeof(HpDataType)*n);
   memcpy(hp->_a, a, sizeof(HpDataType)*n);
   hp->_size = n;
   hp->_capacity = n;
   // 建小堆
   for (int i = (n-1-1)/2; i >= 0; --i)
   {
      AdjustDown(hp->_a, hp->_size, i);
   }
}

4、堆的销毁

void HeapDestory(Heap* hp)
{
   free(hp->_a);
   hp->_size = hp->_capacity = 0;
   hp->_a = NULL;
}

5、向上调整算法(堆排序)

void AdjustUp(int* a, int child)
{
   int parent = (child - 1) / 2;
   while (child > 0)
   {
      if (a[child] < a[parent])
      {
         Swap(&a[child], &a[parent]);
         child = parent;
         parent = (child - 1) / 2;
      }
      else
      {
         break;
      }
   }
}

6、堆的插入

void HeapPush(Heap* hp, HpDataType x)
{
   // 空间不够要增容
   if (hp->_size == hp->_capacity)
   {
      size_t newcapacity = hp->_capacity * 2;
      hp->_a =(HpDataType*)realloc(hp->_a,sizeof(HpDataType)*newcapacity);
      hp->_capacity = newcapacity;
   }
   hp->_a[hp->_size] = x;
   hp->_size++;
   // 向上调整,调成堆
   AdjustUp(hp->_a, hp->_size - 1);
}

7、堆的删除

void HeapPop(Heap* hp)
{
   Swap(&hp->_a[0], &hp->_a[hp->_size - 1]);
   hp->_size--;
   AdjustDown(hp->_a, hp->_size, 0);
}

8、取堆顶的数据

HpDataType HeapTop(Heap* hp)
{
   return hp->_a[0];
}

9、堆的判空

int HeapEmpty(Heap* hp)
{
   return hp->_size == 0 ? 1 : 0;
}

10、堆的打印

void HeapPrint(Heap* hp)
{
   for (int i = 0; i < hp->_size; ++i)
   {
      printf("%d ", hp->_a[i]);
   }
   printf("\n");
}

11、TopK问题

// 最大十个数
void PrintTopK(int* a, int n, int k)
{
   // k个数的小堆
   Heap hp;
   HeapCreate(&hp, a, k);
   for (int i = k; i < n; ++i)
   {
      // 比堆顶的数据要大,就替代它
      if (HeapTop(&hp) < a[i])
      {
         HeapPop(&hp);
         HeapPush(&hp, a[i]);
      }
   }
   HeapPrint(&hp);
}
void TestTopk()
{
	int n = 10000;
	int* a = (int*)malloc(sizeof(int)*n);
	srand(time(0));
	for (size_t i = 0; i < n; ++i)
	{
		a[i] = rand() % 1000000;
	}
	a[15] = 1000000 + 1;
	a[1231] = 1000000 + 2;
	a[531] = 1000000 + 30;
	a[5121] = 1000000 + 4;
	a[115] = 1000000 + 5;
	a[2335] = 1000000 + 6;
	a[9999] = 1000000 + 7;
	a[760] = 1000000 + 8;
	a[423] = 1000000 + 9;
	a[3144] = 1000000 + 10;
	PrintTopK(a, n, 10);
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值