堆的C++实现

  • 性质: 1.堆是一颗完全二叉树,用数组实现。
       2.堆中存储数据的数据是局部有序的。
  • 最大堆:1.任意一个结点存储的值都大于或等于其任意一个子结点中存储的值。
         2.根结点存储着该树所有结点中的最大值。
  • 最小堆:1.任意一个结点存储的值都小于或等于其惹你一个子结点存储的值。
         2.根结点存储着该树所有结点中的最小值。
  • 无论最小堆还是最大堆,任何一个结点与其兄弟结点之间都没有必然联系。
  • 以下给出最大堆的类声明及其成员函数的实现:
template<typename E> class heap{
private:
    E* Heap;    //堆序列的指针
    int maxsize;   //堆的最大容量
    int n;      //堆里面的元素数量

    //将元素放在它应在的位置
    void siftdown(int pos)
    {
        while (!isLeaf(pos))
        {
            int j = leftchild(pos); 
            int rc = rightchild(pos);
            if ((rc < n)&& prior(Heap[rc], Heap[j]))
                j = rc;
            if (prior(Heap[pos], Heap[j]))    return;
            swap(Heap, pos, j);
            pos = j;
        }
    }
public:

    //构造函数
    heap(E* h, int num, int max)
    {
        Heap = h; n = num; maxsize = max;
        buildHeap();
    }
    //返回堆的大小
    int size() const
    {return n;}
    //判断是否为叶节点
    bool isLeaf(int pos) const
    {
        return (pos >= n / 2) && (pos < n);
    }
    //返回左节点
    int leftchild(int pos) const
    {
        return 2 * pos + 1;
    }
    //返回右节点
    int rightchild(int pos) const
    {
        return 2 * pos + 2;
    }
    //返回父节点
    int parent(int pos) const
    {
        return (pos - 1) / 2;
    }
    //建堆
    void buildHeap()
    {
        for (int i = n / 2 - 1; i >= 0; i--) siftdown(i);
    }
    //插入一个元素
    void insert(const E& it)
    {
        assert(n < maxsize, "Heap is full");
        int curr = n++;
        Heap[curr] = it;
        while ((curr != 0) && (prior(Heap[curr], Heap[parent(curr)])))
        {
            swap(Heap, curr, parent(curr));
            curr = parent(curr);
        }
    }
    //移除根节点
    E removefirst()
    {
        assert(n > 0, "Heap is empty");
        swap(Heap, 0, --n);
        if (n != 0)siftdown(0);
        return Heap[n];
    }
    //移除任意一个元素
    E remove(int pos)
    {
        assert((pos >= 0)&&(pos < n), "Bad position");
        if (pos == (n - 1)) n--;
        else
        {
            swap(Heap, pos, --n);
            while ((pos) != 0 && (prior(Heap[pos], Heap[parent(pos)])))
            {
                swap(Heap, pos, parent(pos));
                pos = parent(pos);
            }
            if (n != 0) siftdown(pos);
        }
        return Heap[n];
    }
    //判断第一个参数是否再第二个参数之前
    bool prior(E a, E b)
    {

        if (a > b)   return true;
        else return false;
    }
    //交换值
    void swap(E* heap, int i, int j)
    {
        E temp;
        temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
    //打印
    void print()
    {
        for (int i = 0; i < n; i++)
        {
            cout << Heap[i] << " ";
        }
        cout << endl<<endl;
    }
    };
C++ 中,Epoll 是 Linux 系统提供的一种高效事件监听机制,常用于实现非阻塞的网络编程中的 I/O 多路复用。Epoll 反应是一种基于 epoll 的事件驱动模型,它允许多个套接字在一个单个的 epoll 文件描述符上注册并等待多个事件发生。 以下是基本步骤来在 C++实现一个简单的 Epoll 反应: 1. **包含头文件**: ```cpp #include <iostream> #include <sys/epoll.h> #include <unistd.h> ``` 2. **创建 epoll 实例**: ```cpp int epoll_fd = epoll_create1(0); if (epoll_fd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } ``` 3. **注册套接字**: 当需要监听的套接字准备好接收数据时,将其添加到 epoll 集合中: ```cpp struct epoll_event event; event.events = EPOLLIN; // 监听读事件 event.data.fd = socket_fd; // 替换为实际的套接字描述符 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &event); ``` 4. **轮询事件**: ```cpp while (true) { epoll_event events[EPOLL_MAX_EVENTS]; int num_events = epoll_wait(epoll_fd, events, EPOLL_MAX_EVENTS, -1); // 检查事件 for (int i = 0; i < num_events; i++) { if (events[i].data.fd == -1) { // 退出标志 break; } // 根据事件处理相应的套接字操作 handle_socket_event(events[i]); } } ``` 5. **处理事件**: ```cpp void handle_socket_event(const epoll_event& event) { if (event.events & EPOLLIN) { read_from_socket(event.data.fd); // 从套接字读取数据 } else if (event.events & EPOLLOUT) { write_to_socket(event.data.fd); // 向套接字发送数据 } // 更新事件状态或其他操作... } ``` 6. **关闭 epoll**: 在完成所有操作后记得释放资源: ```cpp close(epoll_fd); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值