ADS之初学左倾堆

前言

最近在高级数据结构课上学习了各种复杂的数据结构,写了二叉树,斐波那契堆之后想着写一下左倾堆试试。小肝一会总算写了个简化版的出来。主要包括查找,插入,删除,合并等操作。供各位同袍参考。

结构类型定义

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找了半个多小时才找到。。。以后一定要更认真一些。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值