• heap(堆)


    二叉堆:

      以前写过二叉堆,但很少使用,快忘了。最近又查了一些关于堆的资料,于是重新熟悉一下这种数据结构。

      一个快速又简单的方式建立二叉堆,仅使用简单vector(或者数组也行):

    #include "stdafx.h"
    #include <iostream>
    #include <vector>
    
    #define LeftChild(i) ((i << 1) | 1)
    #define RightChild(i) (i << 1)
    
    template<class T>
    void swap(T & a, T & b)
    {
    	T tem = a;
    	a = b;
    	b = tem;
    }
    
    class Heap {
    public:
    	/* 上滤插入 */
    	void up_insert(int val, std::vector<int> & values, int top);
    
    	/* 调用上滤插入建立堆 */
    	void up2build(std::vector<int> & values);
    
    	/* 下滤插入 */
    	void down_insert(std::vector<int> & values, int i, int size);
    
    	/* 调用下滤插入建立堆 */
    	void down2build(std::vector<int> & values);
    
    	/* 堆排序 */
    	void sort(std::vector<int> & values);
    };
    
    void Heap::up_insert(int val, std::vector<int> & values, int top)
    {
    	size_t i;
    	for (i = top; i > 0 && values[i >> 1] < val; i >>= 1)
    		values[i] = values[i >> 1];
    	values[i] = val;
    }
    
    void Heap::up2build(std::vector<int> & values)
    {
    	int top = 0;
    	for (auto v : values)
    	{
    		up_insert(v, values, top);
    		++top;
    	}
    }
    
    void Heap::down_insert(std::vector<int> & values, int i, int size)
    {
    	int last = values[i];
    	for (int Child; LeftChild(i) < size; i = Child)
    	{
    		Child = LeftChild(i);
    		if (Child != size - 1 && values[Child + 1] > values[Child])
    			Child++;
    
    		if (last < values[Child])
    			values[i] = values[Child];
    		else
    			break;
    	}
    	values[i] = last;
    }
    
    void Heap::down2build(std::vector<int> & values)
    {
    	int size = values.size() - 1;
    	for (int i = size >> 1; i >= 0; i--)
    	{
    		down_insert(values, i, size);
    	}
    }
    
    void Heap::sort(std::vector<int> & values)
    {
    	int size = values.size() - 1;
    	down2build(values);
    	for (int i = size; i > 0; i--)
    	{
    		swap(values[0], values[i]);
    		down_insert(values, 0, i);
    	}
    }
    
    int main()
    {
    	Heap heap;
    	std::vector<int> values { 5345,332,2341,498,248,89,239,4825,8,43,9892,872,1843 };
    	
    	//heap.build(values);
    	heap.sort(values);
    
    	for (auto v : values)
    		std::cout << v << std::endl;
    	
    	getchar();
    	return 0;
    }

      up_build是形如‘上滤’的过程,平均情况时间复杂度为θ(n),因为up_insert函数平均只花费θ(1)的时间。空间复杂度O(n);

      down_build是形如‘下滤’的过程,时间复杂度为O(nlgn),空间复杂度O(n)。

     左式堆:

      左式堆的性质:任意节点的左孩子的NPL(null path length - 零路径长)至少等于右孩子的NPL,这样的条件使得左式堆十分不平衡。左式堆的基本操作是进行堆合并。

      NPL的定义:任一节点到叶节点的最短路径的长。

      参考资料:

        1.《数据结构与算法分析》第6章 - 堆。

        2.知乎相关问题

  • 相关阅读:
    Dapr+Kubernetes 实战一
    C# 强大的新特性 Source Generator
    Go语言之网络编程
    GORM系列之创建数据
    Gin框架系列之表单验证
    GORM系列之快速入门
    Gin框架系列之请求参数传递
    Gin框架系列之中间件
    Gin框架系列之优雅重启或关闭
    Go语言之反射
  • 原文地址:https://www.cnblogs.com/darkchii/p/8542145.html
Copyright © 2020-2023  润新知