C语言刷 堆(优先队列)

摘要:
703.数据流中第K大元素/*小型根堆*/typedefstruct{intheapCapacity;intheapSize;int*heap;}KthLargest/*顶部下标:0;双亲:(k-1)/2;leftChild:2*k+1;RightChild:2*k+2*/intPrentIndex{return(i-1)/2;}intLeftChildIndex{return2*i+1;}int RightChildIndex{return2*i+2;}void Swap{inttmp=*a;*a=*b;*b=tmp;}/**************************************,与父节点交换*/void Swim{当{Swap;i=ParentIndex;//浮起一次时,更新下次可能浮起的索引}}/*下沉:*不符合规则的点,与子节点中较小的值交换*/void Sink{while{int smallOneIndex=LeftChildIndex;int leftVal=heap[LeftChildIndex];if{int rightVal=heap[RightChildIndex];//比较子节点中哪个较小的smallOneIndex=leftVal˂rightVal?

703. 数据流中的第 K 大元素

/* 小根堆 */
typedef struct {
    int heapCapacity;
    int heapSize;
    int *heap;
} KthLargest;

/* 堆顶下标: 0; parent: (k-1)/2; leftChild: 2*k + 1; rightChild: 2*k + 2 */
int ParentIndex(int i)
{
    return (i - 1) / 2;
}

int LeftChildIndex(int i)
{
    return 2 * i + 1;
}

int RightChildIndex(int i)
{
    return 2 * i + 2;
}

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

/************************************ 堆的有序性的维护 ************************************/
/*
* 上浮:
*     不符合规则的点(这里是小根堆,规则即父节点最小),与父节点交换(直至符合为止)        
*/
void Swim(int *heap, int i)
{
    while (i > 0 && heap[ParentIndex(i)] > heap[i]) {
        Swap(&heap[ParentIndex(i)], &heap[i]);
        i = ParentIndex(i); // 已经上浮一次,更新下次可能上浮的索引
    }
}

/*
* 下沉:
*     不符合规则的点(这里是小根堆,规则即父节点最小),与子节点中较小的(因为是小根堆)交换(直至符合为止)        
*/
void Sink(int *heap, int heapSize, int i)
{
    while (LeftChildIndex(i) < heapSize) {
        int smallOneIndex = LeftChildIndex(i);
        int leftVal = heap[LeftChildIndex(i)];
        if (RightChildIndex(i) < heapSize) {
            int rightVal = heap[RightChildIndex(i)];
            // 比较子节点中哪个更小
            smallOneIndex = leftVal < rightVal ? smallOneIndex : RightChildIndex(i);
        }
    
        if (heap[i] < heap[smallOneIndex]) {
            break;
        }

        Swap(&heap[i], &heap[smallOneIndex]);
        i = smallOneIndex; // 已经下沉一次,更新下次可能上浮的索引
    }
}

/*
* 出队:
*     1.最后一个点换到根(根即待出队的点)
*     2.下沉
*/
void Pop(int *heap, int *heapSize)
{
    Swap(&heap[0], &heap[*heapSize - 1]);
    // heap[*heapSize - 1] = 0;
    (*heapSize)--;
    Sink(heap, *heapSize, 0);
}

/*
* 入队:
*     1.待插入的点放在最后
*     2.上浮
*/
void Push(int *heap, int *heapSize, int val)
{
    heap[(*heapSize)++] = val;
    Swim(heap, *heapSize - 1);
}

/************************************ 答题 ************************************/
int kthLargestAdd(KthLargest* obj, int val) 
{
    if (obj->heapCapacity > obj->heapSize) {
        Push(obj->heap, &obj->heapSize, val);
    } else if (val > obj->heap[0]) {
        // 队列已经满了,并且头节点小于待插入的值
        Pop(obj->heap, &obj->heapSize);
        Push(obj->heap, &obj->heapSize, val);
    }

    // 小根堆,每次返回头节点
    return obj->heap[0];
}

KthLargest* kthLargestCreate(int k, int* nums, int numsSize) 
{
    if (k < 1) {
        return NULL;
    }

    KthLargest *obj = (KthLargest *)malloc(sizeof(KthLargest));
    obj->heapCapacity = k;
    obj->heapSize = 0;
    obj->heap = (int *)malloc(sizeof(int) * k);
    memset(obj->heap, 0, sizeof(int) * k);

    for (int i = 0; i < numsSize; i++) {
        if (obj->heapCapacity > obj->heapSize) {
            Push(obj->heap, &obj->heapSize, nums[i]);
        } else {
            // 堆已经满了,调用add接口
            int ret = kthLargestAdd(obj, nums[i]);
        }
    }

    return obj;
}

void kthLargestFree(KthLargest* obj) 
{
    if (obj != NULL) {
        free(obj->heap);
        free(obj);
    }

}

/**
 * Your KthLargest struct will be instantiated and called as such:
 * KthLargest* obj = kthLargestCreate(k, nums, numsSize);
 * int param_1 = kthLargestAdd(obj, val);
 
 * kthLargestFree(obj);
*/

347. 前 K 个高频元素

C语言刷 堆(优先队列)第1张

解法1:直接用UT_HASH中的排序,返回前k个元素

struct hashTable {
    int key;    // 数组元素
    int value;  // 数组元素出现的频率
    UT_hash_handle hh;
};

struct hashTable *g_hash;

void AddNode(int num)
{
  struct hashTable *tmp = NULL;
  HASH_FIND_INT(g_hash, &num, tmp);
  if (tmp == NULL) {
      tmp = (struct hashTable *)malloc(sizeof(struct hashTable));
      tmp->key = num;
      tmp->value = 1;
      HASH_ADD_INT(g_hash, key, tmp);
  } else {
      (tmp->value)++;
  }
}

/* 排序:逆序 */
int HashCmp(struct hashTable *a, struct hashTable *b)
{
    return b->value - a->value;
}

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* topKFrequent(int* nums, int numsSize, int k, int* returnSize)
{
    g_hash = NULL;
    for (int i = 0; i < numsSize; i++) {
        // 插入到hash表中
        AddNode(nums[i]);
    }

    // 根据数组元素出现的频次,对hash表进行降序
    HASH_SORT(g_hash, HashCmp);

    int *res = (int *)malloc(sizeof(int) * k);
    *returnSize = k;
    int cnt = 0;
    // 对hash表进行遍历
    struct hashTable *cur, *tmp;
    HASH_ITER(hh, g_hash, cur, tmp) {
        if (cnt == k) {
            break;
        }
        res[cnt++] = cur->key;
    }
    return res;
}

解法2:利用最小堆

免责声明:文章转载自《C语言刷 堆(优先队列)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇华为网络设备常用命令用Socket开发的一枚小型实时通信App下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ZeroMQ示例(C/C++/PHP)详解三种模式

源自:https://blog.csdn.net/qq_16836151/article/details/521081521、应答模式2、均衡分配模式(推拉模式)3、发布订阅模式(天气预报) 提问-回答 让我们从简单的代码开始,一段传统的Hello World程序。我们会创建一个客户端和一个服务端,客户端发送Hello给服务端,服务端返回World。下文是...

用C语言实现一个简单的HTTP客户端(HTTP Client)

用C语言实现一个简单的HTTP客户端(HTTP Client) - 雨水的专栏 - 博客频道 - CSDN.NET 用C语言实现一个简单的HTTP客户端(HTTP Client) 分类:2. C/C++语言2007-04-03 23:304632人阅读评论(4)收藏举报 用C语言实现一个简单的HTTP Client(HTTP客户端) 作者:g...

c语言进阶6-指针

指针是c语言的一个重要组成部分 是c语言的核心、精髓所在,用好指针可以在c语言编程中起到事半功倍的效果。一方面,可以提高程序的编译效率和执行速度以及实现动态的存储分配;另一方面,使用指针可使程序更灵活,全球表示各种数据结构,编写高质量的程序。 指针是c语言显著的优点之一,其使用起来十分灵活而且能提高某些程序的效率,但是如果使用不当则很容易造成系统错误。许多...

iOS用域名或主机名获取IP地址(包含C语言接口 和iOS原生)

   最近工作中遇到了个新需求、需要将域名 解析成ip地址,搜了搜文章博客,发现很多人都是在用C的 structhostent*gethostbyname(constchar*); 对于OC原生的方法还是比较陌生的,因此研究了一下,封了个方法出来,供大家参考使用,话不多说、上代码 1 #import "TestTools.h" 2 3 #include...

C语言之大整数加法

1 #include<stdio.h> 2 #include<string.h> 3 4 void reverse( char *s ) /*将字符串逆置*/ 5 { 6 int length; 7 int i = 0; 8 char temp; 9 length...

C语言中宏的作用

在C语言#define机制中包括了一个规定,与允许把参数替换到文本中,这种实现通常称为宏或宏定义。下面是宏的声明方式: #define name(parameter-list) stuff 其中 parameter-list的左括号必须与name紧邻,如果中间有空白,parameter-list就会被解释为stuff的一部分。 宏的作用 1.替换作用:在程...