树的储存形势&代码实现(跑路人笔记2)

简介: 树的储存形势&代码实现(跑路人笔记)

main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
//堆的测试
void HeapTest()
{
  Heap hp = {0};
  HeapCreat(&hp);
  HeapPush(&hp, 10);
  HeapPush(&hp, 18);
  HeapPush(&hp, 19);
  HeapPush(&hp, 25);
  HeapPush(&hp, 28);
  HeapPush(&hp, 43);
  HeapPush(&hp, 65);
  HeapPush(&hp, 49);
  HeapPush(&hp, 27);
  HeapPush(&hp, 37);
  HeapPop(&hp);
  HeapPrint(&hp);
  HeapDestory(&hp);
}
//堆排序
void HeapSort(int* a, int size)
{
  Heap hp;
  HeapCreat(&hp);
  for (int i = 0; i < size; ++i)
  {
    HeapPush(&hp, a[i]);
  }
  size_t j = 0;
  while (!HeapEmpty(&hp))
  {
    a[j] = HeapTop(&hp);
    j++;
    HeapPop(&hp);
  }
  HeapDestory(&hp);
}
int main()
{
  //TestHeap();
  int a[] = { 4, 2, 7, 8, 5, 1, 0, 6 };
  HeapSort(a, sizeof(a) / sizeof(int));
  for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
  {
    printf("%d ", a[i]);
  }
  printf("\n");
  return 0;
}

咱主要讲Heap.c所需要讲解的部分

主要讲解部分

下方是结构题的内容

typedef struct Heap
{ 
  HPDataType* data;//用于储存数据
  size_t size; //大小
  size_t capacity;//容量
}Heap;

实话实说需要重点讲解的主要是两个函数.

其中

void AdJustUp(Heap* obj)
{
  size_t child = obj->size-1;
  size_t parent = (child - 1) / 2;
  while (child)
  {
    if (obj->data[parent] > obj -> data[child])
    {
      HPDataType tmp = obj->data[child];
      obj->data[child] = obj->data[parent];
      obj->data[parent] = tmp;
      child = parent;
      parent = (child - 1) / 2;
    }
    else
    {
      break;
    }
  }
}

这个函数是嵌套在HeapPush中的一个用于调整数据位置的函数,我们在HeapPush的时候是将数据直接放在我们顺序表的末尾处,然后通过AdJustUp函数对数据进行调整.将本来插入后可能不是堆情况调整成堆的格式.


我们通过图来了解这种情况: 比如我们的数值原来有着: 2 3 5 6 7 8


image.png


这时我们插入一个1来看看我们的AdJustUp函数是如何将顺序表的储存情况重新换成堆形势.


image.png


其实很简单我们通过while循环和if语句来判断末尾部的父亲是否大于我们要改变位置的节点如果大于就交换他们的位置如果小于就直接进行break语句跳出循环即可.


image.png


然后使我们的向下调整函数.

void AdJustDown(Heap* obj)
{
  size_t father = 0;
  size_t child = father*2+1;//得到的是左孩子
  while (child < obj->size)
  {
    //选出最小的孩子
    if (child+1<obj->size&&obj->data[child] > obj->data[child + 1])
    {
      child++;
    }
    if (obj->data[child] < obj->data[father])
    {
      HPDataType tmp = obj->data[child];
      obj->data[child] = obj->data[father];
      obj->data[father] = tmp;
      father = child;
      child = father * 2 + 1;
    }
    else
    {
      break;
    }
  }
}
void HeapPop(Heap* obj)
{
  assert(obj);
  assert(obj->size > 0);
  obj->data[0] = obj->data[obj->size - 1];
  obj->size--;
  AdJustDown(obj);
}


我们的向下调整函数也是在HeapPop函数内作为内嵌(至于为啥要把向下调整专门分装成一个函数,我个人认为是为了代码的整洁性吧).


HeapPop 的功能是删除顺序表的定元素也就是下标为0的元素,但是我们如果先将下标为0的元素换成我们在尾的元素然后进行对size进行--即可.


然后我们即可进行向下调整的操作.


老样子我们使用图文调整的形式给大家展示.


image.png


我们先比较左右还在的大小选一个最小的与父亲节点交换在只有一个孩子的情况至于左孩子比较即可👍.


结尾

这部分的代码实现其实也挺简单的,我们想用堆排序也只需要从得到头元素然后删头只要堆为空即可👍.


相关文章
|
1月前
|
存储 缓存 安全
几道 C/C 题涉及的知识盲区
几道 C/C 题涉及的知识盲区
|
机器学习/深度学习 算法 图计算
代码随想录训练营day59| 503.下一个更大元素II 42. 接雨水
代码随想录训练营day59| 503.下一个更大元素II 42. 接雨水
|
编解码 应用服务中间件 数据安全/隐私保护
从零开始的内存马分析——如何骑马反杀(一)2
从零开始的内存马分析——如何骑马反杀(一)
81 0
|
存储 安全 Java
从零开始的内存马分析——如何骑马反杀(一)3
从零开始的内存马分析——如何骑马反杀(一)
382 0
|
网络虚拟化 数据安全/隐私保护
从零开始的内存马分析——如何骑马反杀(二)1
从零开始的内存马分析——如何骑马反杀(二)
2647 0
|
SQL Linux
从零开始的内存马分析——如何骑马反杀(二)2
从零开始的内存马分析——如何骑马反杀
164 0
|
Oracle 安全 关系型数据库
从零开始的内存马分析——如何骑马反杀(三)3
从零开始的内存马分析——如何骑马反杀(三)
673 0
|
网络协议 Java 数据库
从零开始的内存马分析——如何骑马反杀(三)1
从零开始的内存马分析——如何骑马反杀(三)
124 0
|
JSON 编解码 安全
从零开始的内存马分析——如何骑马反杀(一)1
从零开始的内存马分析——如何骑马反杀(一)
1064 0
|
Java
从零开始的内存马分析——如何骑马反杀(三)2
从零开始的内存马分析——如何骑马反杀(三)
141 0

热门文章

最新文章