堆的相关运算

堆的相关内容:

  • 建堆:堆是利用一个数组来进行创建的
  • 建堆的思路:堆分为大堆和小堆,建堆时是从最后一个根节点开始进行调整,假设左右结点的堆已经满足堆的性质,所以,每进行调整一次堆的根节点之后就要向下调整。

  • 堆的删除:当然是进行头删,这样才具有挑战性,尾删不影响堆的性质。

  • 头删
  • 1.把让第一个元素的值等于最后一个元素
  • 2.进行向下调整
  • 3.数组的大小减1

  • 尾插:尾插需要判断插入的数冲洗构建而成的堆是否还满足堆的性质,采取向上调整

  • 堆排序:1.升序->建大堆;降序->建小堆。2.建完堆之后每次进行把第一个数和最后一个数进行交换。然后把size-1-i个数从根节点开始进行向下调整,直到交换完所有的数(建堆,交换,调整)

以下为代码实现:
heap.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

#define MAX_SIZE 100

typedef struct Heap{
    int arr[MAX_SIZE];
    int size;
}Heap;

//堆的初始化
void InitHeap(Heap * pH,int arr[],int size);
//堆的创建
void MakeHeap(Heap * pH);
//向下调整
void AdjustDown(Heap *pH,int root);
//交换
void Swap(int *p1, int *p2);
//打印
void print(Heap *pH);
//堆的尾插
void PushHeap(Heap * pH, int data);
//向上调整
void AdjustUp(Heap *pH, int child);
//堆的删除(头删,比较有意思)
void PopHeap(Heap *pH);
//堆排序
void HeapSort(int arr[],int size);
//大堆的向下调整
void MaxAdjustDown(int arr[],int size, int parent);
heap.c
#include"heap.h"

//堆的初始化
void InitHeap(Heap * pH, int arr[], int size)
{
    assert(pH);
    assert(pH->size);
    memcpy(pH->arr, arr, sizeof(int)*size);
    pH->size = size;
}

//堆的创建
void MakeHeap(Heap *pH)
{
    int left,right,i;
    for (i = (pH->size - 2) / 2; i >= 0; i--)
    {
        left = 2 * i + 1;
        right = 2 * i + 2;
        int minchild = left;
        if (pH->arr[left] > pH->arr[right])
        {
            minchild = pH->arr[right];
        }
        if (pH->arr[i] > pH->arr[minchild])
        {
            Swap(pH->arr + i, pH->arr + minchild);
        }
        AdjustDown(pH,minchild);
    }
}

//向下调整
1.递归
//void AdjustDown(Heap *pH,int parent)
//{
//  int left = 2 * parent + 1;
//  int right = 2 * parent + 2;
//  int minchild = left;
//  //是叶子结点的时候
//  if (left >= pH->size)
//  {
//      return;
//  }
//
//  if (right <pH->size&&pH->arr[left] > pH->arr[right])
//  {
//      minchild = right;
//  }
    /*if (pH->arr[parent] <= pH->arr[minchild])
    {
        return;
    }
    Swap(pH->arr + parent, pH->arr + minchild);*/
//  AdjustDown(pH, minchild);
//}
//2.循环
void AdjustDown(Heap * pH, int parent)
{
  while (parent<pH->size){
    //判断是否是叶子结点
    int left = 2 * (parent)+1;
    int right = 2 * (parent)+2;
    if (left >= pH->size)
    {
        return;
    }
    //向下调整的过程是一个循环
        int minchild = left;
        if (right <pH->size&&pH->arr[left] > pH->arr[right])
        {
             minchild = right;
        }
        if (pH->arr[minchild] >= pH->arr[parent])
        {
            return;
        }
        Swap(pH->arr + minchild, pH->arr + parent);

        parent = minchild;
    }

}
void Swap(int *p1, int *p2)
{
    int tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

void print(Heap *pH)
{
    int i = 0;
    for (i = 0; i < pH->size; i++)
    {
        printf("%d ", pH->arr[i]);
    }
    printf("\n");
}

//堆的尾插
void PushHeap(Heap *pH, int data)
{
    assert(pH);
    assert(0<pH->size<MAX_SIZE);
    pH->arr[pH->size] = data;
    pH->size++;
    AdjustUp(pH, pH->size - 1);
}

//向上调整
1.递归
//void AdjustUp(Heap *pH, int child)
//{
//  int parent = (child - 1) / 2;
//  if (pH->arr[parent] <= pH->arr[child])
//  {
//      return;
//  }
//  Swap(pH->arr+parent, pH->arr+child);
//if (parent == 0)
//{
//  return;
//}
//  AdjustUp(pH, parent);
//
//}
//2.循环
void AdjustUp(Heap * pH, int child)
{
    while (child >0)
    {
        int parent = (child - 1) / 2;
        if (pH->arr[child] < pH->arr[parent])
        {
            Swap(pH->arr + parent, pH->arr + child);
        }
        if (parent == 0)
        {
            return;
        }
        child = parent;
    }
}

//头删
void PopHeap(Heap * pH)
{
    assert(pH);
    pH->arr[0] = pH->arr[--pH->size];
    AdjustDown(pH, 0);
}
//堆排序(建大堆的过程)
void HeapSort(int arr[],int size)
{
    int i,j;
        for (i = (size - 2) / 2; i >= 0; i--)
        {
            int left = 2 * i + 1;
            int right = 2 * i + 2;
            int maxchild = left;
            if (right <size&&arr[left] <arr[right])
            {
                maxchild = right;
            }
            if (arr[maxchild]>arr[i])
            {
                Swap(arr + i, arr + maxchild);
                MaxAdjustDown(arr, size, maxchild);
            }   
    }
        for (j = 0; j < size; j++)
        {
            Swap(arr, arr+size - 1 - j);
            MaxAdjustDown(arr,size - j - 1,0);
        }
}

//大堆的向下调整
void MaxAdjustDown(int arr[],int size, int parent)
{
    int left = 2 * parent + 1;
    int right = 2 * parent + 2;
    int maxchild = left;
    if (left >= size)
    {
        return;
    }
    if (right<size&&arr[left] < arr[right])
    {
        maxchild = right;
    }
    if (arr[parent]>arr[maxchild])
    {
        return;
    }
    Swap(arr + parent, arr+maxchild);

    MaxAdjustDown(arr,size, maxchild);
}

main.c
#include"heap.h"
int main(void)
{
    int arr1[9] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
    int arr2[] = { 2, 0, 1, 8, 4, 6, 7, 9 };
    int size1 = sizeof(arr1) / sizeof(arr1[0]);
    int size2 = sizeof(arr2) / sizeof(arr2[0]);
    Heap heap;
    InitHeap(&heap, arr1, size1);
    MakeHeap(&heap);
    print(&heap);
    PushHeap(&heap, 13);
    PushHeap(&heap, 89);
    print(&heap);
    PopHeap(&heap);
    print(&heap);
    HeapSort(arr2,size2);
    int i = 0;
    for (i = 0; i < size2; i++)
    {
        printf("%d ", arr2[i]);
    }
    printf("\n");

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值