【数据结构】--》堆的一些简单实现

堆分为两种

**a,小堆**
  如果一个关键码的集合K={k0,k1,k2,...,kn-1},把它所有的元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:
  Ki<=K2*i+1 且 Ki<=K2*i+2 
  则称之为“小堆”;
**b,大堆**
  如果一个关键码的集合K={k0,k1,k2,...,kn-1},把它所有的元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:
  Ki>=K2*i+1 且 Ki>=K2*i+2 
  则称之为“大堆”;

下面是一些关于堆操作的一些简单实现(C语言)

下面对堆的实现既可以创建最大堆也可以创建最小堆
1,堆的初始化 —-》 2,创建堆 –》3,在堆中插入值为data的元素–》4,检测堆是否为空 –》5,获取堆中元素的个数 –》6,获取堆顶元素 –》7,删除堆顶的元素 –》8,销毁堆 –.》9,用于元素比较的比较器 ( 小于号 ,大于号);

Heap.c

//检查是否需要增容
void Capacity(Heap* hp)
{
    assert(hp);
    if (hp->_capacity == hp->_size)
    {
        DataType* pNewNode = NULL;
        hp->_capacity = hp->_capacity * 2;
        pNewNode = (DataType*)realloc(hp->_array, sizeof(DataType)*(hp->_capacity));
        if (NULL == pNewNode)
        {
            assert(0);
            return;
        }
        hp->_array = pNewNode;
    }
}

//交换两数内容
void swap(int* left, int* right)
{
    assert(left);
    assert(right);
    int temp = *left;
    *left = *right;
    *right = temp;
}

//最大堆
int Greater(DataType x, DataType y)
{
    return x < y;
}
//最小堆
int less(DataType x, DataType y)
{
    return x > y;
}

//向下调整
void AdjustDown(Heap* hp, int parrent,Compare com)
{
    assert(hp);
    int lChild = 2 * parrent + 1;
    while (lChild < hp->_size)
    {
        if (lChild + 1 <= hp->_size - 1 && com(hp->_array[lChild] , hp->_array[lChild + 1]))
            lChild += 1;

        if (com(hp->_array[parrent] , hp->_array[lChild]))
        {
            swap(&hp->_array[parrent], &hp->_array[lChild]);
            parrent = lChild;
            lChild = 2 * parrent + 1;
        }
        else
            return;
    }
}

// 堆的初始化 
void InitHeap(Heap* hp, Compare com)
{
    assert(hp);
    hp->_capacity = 3;
    hp->_array = (DataType*)malloc(hp->_capacity*sizeof(DataType));
    hp->_size = 0;
    hp->_com = NULL;
}

// 创建堆 
void CreateHeap(Heap* hp, DataType* array, int size, Compare com)
{
    assert(hp);
    assert(array);
    int root = (size - 2) >> 1;
    for (int i = 0; i < size; i++)
    {
        Capacity(hp);
        hp->_array[hp->_size++] = array[i];
    }
    for (; root >= 0; root--)
    {
        AdjustDown(hp, root,com);
    }
}

//向上调整
void AdjustUp(Heap* hp,int child,Compare com)
{
    assert(hp);
    int parrent = (child - 1) >> 1;
    while (parrent>=0)
    {
        if (com(hp->_array[parrent], hp->_array[child]))
        {
            swap(&hp->_array[parrent], &hp->_array[child]);
            child = parrent;
            parrent = (child - 1) >> 1;
        }
        else
            return;
    }
}
// 在堆中插入值为data的元素 
void InsertHeap(Heap* hp, DataType data,Compare com)
{
        assert(hp);
        Capacity(hp);   
        hp->_array[hp->_size++] = data;
        AdjustUp(hp, hp->_size - 1, com);
}

// 检测堆是否为空 
int EmptyHeap(Heap* hp)
{
    assert(hp);
    return 0 == hp->_size;
}

// 获取堆中元素的个数 
int SizeHeap(Heap* hp)
{
    assert(hp);
    return hp->_size;
}

// 获取堆顶元素 
DataType TopHeap(Heap* hp)
{
    assert(hp);
    return hp->_array[0];
}

// 删除堆顶的元素 
void DeleteHeap(Heap* hp,Compare com)
{
        assert(hp);
        hp->_array[0] = hp->_array[hp->_size-- - 1];
        AdjustDown(hp, 0,com);
}

// 销毁堆 
void DestroyHeap(Heap* hp)
{
        assert(hp);
        free(hp->_array);
        hp->_array = NULL;
        hp->_capacity = 0;
        hp->_size = 0;
        hp->_com = NULL;
}

测试代码:

void testHeap()
{
    Heap hp;
    int ret = -1;
    int arr[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
    InitHeap(&hp, less);
    //CreateHeap(&hp, arr, sizeof(arr) / sizeof(arr[0]), less);
    Compare com = Greater;
    CreateHeap(&hp, arr, sizeof(arr) / sizeof(arr[0]), com);
    InsertHeap(&hp, 0,com);
    InsertHeap(&hp, 50,com);
    InsertHeap(&hp, 0,com);
    InsertHeap(&hp, 100,com);
    ret = TopHeap(&hp);
    if (EmptyHeap(&hp))
    {
        printf("是空堆\n");
    }
    else
        printf("不是空堆\n");

    ret = SizeHeap(&hp);
    DeleteHeap(&hp,com);
    ret = SizeHeap(&hp);
    DestroyHeap(&hp);
}

**

总结:

堆的实现主要是向下调整方法

*向下调整方法:*
找到最后一个非叶子结点下标假设为parent;
找到该节点的左孩子left=2*parent+1;
如果右孩子right=2*parent+2存在,找到left和right中最小的孩子;
比较parent是否小于最小者,如果小于等于最小者,调整结束,否则,交换两数;
继续,知道满足堆的性质为止;

**
下篇博客会对堆的一些应用进行实现;

———————————————–end—————————————————–

猜你喜欢

转载自blog.csdn.net/eternal_01/article/details/80421955