前言
最近在高级数据结构课上学习了各种复杂的数据结构,写了二叉树,斐波那契堆之后想着写一下左倾堆试试。小肝一会总算写了个简化版的出来。主要包括查找,插入,删除,合并等操作。供各位同袍参考。
结构类型定义
typedef int Type;
typedef struct _LeftistNode{
Type key; //键值
int npl; //Null path length零路径长度
struct _LeftistNode *left; //左孩子
struct _LeftistNode *right; //右孩子
}LeftistNode, *LeftistHeap;
源码实现
#include <stdio.h>
#include <stdlib.h>
#include "leftist.h"//头文件,主要包括各种函数和结构类型定义
//---------------------------------------------------------------------------------------以下为具体函数部分
static void swap_node(LeftistNode *m, LeftistNode *n) {
//交换两个结点的值,用temp临时储存。
LeftistNode temp = *m;
*m = *n;
*n = temp;
}
int find_min(LeftistHeap h, int *minimum){
//获取最小值。成功返回0,失败返回-1。
if(h == NULL){
return -1;
}
*minimum = h->key; //获取根节点键值,即为最小值
return 0;
}
//合并左倾堆
LeftistNode *merge_leftist(LeftistHeap m, LeftistHeap n) {
if (m == NULL) {
return n;
}
//如果一个为空,直接返回另一个即可
if (n == NULL) {
return m;
}
if (m->key > n->key) {
//令m作为合并后的根,需保证m->key < n->key
swap_node(m, n);
}
m->right = merge_leftist(m->right, n); //m的右孩子和n合并,合并后的根是m的右孩子。递归合并。
if (m->left == NULL || m->left->npl < m->right->npl) {
//如果m左孩子为空,或m的左孩子的npl小于右孩子的npl,则进行调整——交换m左右孩子。
LeftistNode *temp = m->left;
m->left = m->right;
m->right = temp;
}
//计算新树的npl
if (m->left == NULL || m->right == NULL) {
m->npl = 0;
//左或右子空自然为0
}
else {
m->npl = (m->left->npl > m->right->npl) ? (m->right->npl + 1) : (m->left->npl + 1);
//就是哪个小哪个加一就是npl。。。
}
return m; //返回m(即根节点)
}
LeftistNode *insert_leftist(LeftistHeap h, Type key) {
LeftistNode *node; //新建一个节点
if ((node = (LeftistNode *)malloc(sizeof(LeftistNode))) == NULL) {
return h;
//直接写malloc在VS中会报错。经改进换成此种写法。考虑到新建节点失败的情况
}
//初始化节点
node->key = key;
node -> npl = 0;
node->left = node->right = NULL;
return merge_leftist(h, node); //返回插入新结点后的树的根节点
}
//删除根结点
LeftistNode *delete_leftist(LeftistHeap h) {
if (h == NULL) {
//堆为空直接返回NULL
return NULL;
}
//删除根节点前记下左右孩子
LeftistNode *l = h->left;
LeftistNode *r = h->right;
free(h);
return merge_leftist(l, r);
}
void destroy_leftist(LeftistHeap h){
if (h == NULL) {
//空的直接跳过
return;
}
if (h->left != NULL) {
destroy_leftist(h->left);
}
if (h->right != NULL) {
destroy_leftist(h->right);
}//哪个不空接着删哪个。分别递归即可。
free(h);
}
//打印函数可在这里写
int main(){
//各种函数具体调用以及测试数据可在这里写
return 0;
}
后记
该代码为防止抄袭少了头文件中的一些函数定义,也少了测试数据与打印函数。大家自己补上即可。这个左倾堆程序是为了完成我们组的大程——Dijistra最短路径算法而做的。现在笔者还未完全理解其中如何把图和数据结构结合的方法。之后会再写一篇文章来进行详细描述。
吐槽:在敲程序的时候因为一个变量习惯原因忘了改变量名,结果出bug找了半个多小时才找到。。。以后一定要更认真一些。。。