浙江大学数据结构笔记:堆与并查集

本文介绍了浙江大学的数据结构课程内容,详细阐述了堆(大顶堆和小顶堆概念、创建、插入和删除操作)以及并查集(TSSN实现中的路径压缩和按秩归并)。通过实例展示了如何使用堆和并查集进行数据管理和操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一,堆

堆分为大顶堆和小顶堆
大顶堆每个结点比两个儿子大,小顶堆每个结点比两个儿子小

一般用完全二叉树储存堆

堆的表示

typedef struct HeapStruct *MaxHeap;
struct HeapStruct{
	ElementType *Element;//储存堆元素的数组  指针 
	int Size;//堆当前元素个数 
	int Capacity;//堆的最大容量 
}; 

堆的创建

MaxHeap Creat(int MaxSize)
{
	//创建容量为MaxSize的最大堆
	MaxHeap H=malloc(sizeof(struct HeapStruct));
	H->Element=malloc((MaxSize+1)*sizeof(ElementType));
	H->Size=0;
	H->Capacity=MaxSize;
	H->Element[0]=MaxData;
	//定义哨兵大于堆中所有元素的值,便于以后更快地操作 
	return H;
}

堆的插入

void Insert(MaxHeap H,ElementType item)
{
	int i;
	if(IsFull(H)){
		printf("最大堆已满");
		return;
	}	
	i=++H->Size;//i指向插入后堆中的最后一个元素的位置 
	for(;H->Element[i/2]<item;i/=2)
		H->Element[i]=H->Element[i/2];//向下过滤结点 
	H->Element[i]=item;//将item插入 
} 

堆的删除

先取出树根(最大结点),在把最后一个结点移到树根上,依次与左右儿子比较往下挪直到位置正确
在这里插入图片描述

在这里插入图片描述

ElementType DeleteMax(MaxHeap H)
{
	int Parent,Child;
	ElementType MaxItem ,tmp;
	if(IsEmpty(H)){
		printf("最大堆已为空");
		return;
	}
	MaxItem=H->Element[1];
	//取出根节点最大值
	// 用最大堆中最后一个元素从根结点开始向上过滤下层结点
	tmp=H->Element[H->Size--];//tmp指向最后一个元素
	for(Parent=1;Parent*2<=H->Size;Parent=Child){ //parent=1一开始把最后一个结点放在树根上
        //若2*Parent>size则左儿子超出堆栈,没有左右儿子
		Child=Parent*2;//指向左儿子 
		if((Child!=H->Size)&&(H->Element[Child]<H->Element[Child+1]))
            //Child==Size意味着左儿子为最后一个元素,无右儿子
			Child++;//Child指向左右结子点的最大者 
		if(tmp>=H->Element[Parent]) break;
		//移动tmp元素到下一层 
		else
			H->Element[Parent]=H->Element[Child];//把左右儿子中大的和父节点交换
	} 
	H->Element[Parent]=tmp;
	return MaxItem;
}

二,并查集:TSSN的实现

在这里插入图片描述

下面代码用到了路径压缩和按秩归并**

按秩归并:

做合并操作时把高度小的树合并到高度大的树上,为了节省空间,用S[i]记录树高的负数,不必新开一个数组

路径压缩:

做find操作时同时把一个集合里面的结点连到根节点上,加快以后的find操作

#include<bits/stdc++.h>
using namespace std;
//浙江大学数据结构并查集
//TSSN的实现
const int MaxSize=10010;
typedef int ElementType;
typedef int SetName;//默认根节点的下标为集合的名称 
typedef ElementType SetType[MaxSize]; 
SetName Find(SetType S,ElementType X)
{
	 if(S[X]==-1) //找到集合的根 
	 	return X;
	else
		return S[X]=Find(S,S[X]);//路径压缩 
} 
void Union(SetType S,SetName Root1,SetName Root2)//按秩归并 
{
	if(S[Root1]<S[Root2])
		S[Root1]=Root2;
	else{
		if(S[Root1]==S[Root2]) S[Root1]--;
		S[Root2]=Root1;
	}	
}
void Input_connection(SetType S)
{
	ElementType u,v;
	SetName Root1,Root2;
	cin>>u>>v;
	Root1=Find(S,u-1);
	Root2=Find(S,v-1);
	if(Root1!=Root2)
		Union(S,Root1,Root2); 
}
void Check_connection(SetType S)
{
	ElementType u,v;
	SetName Root1,Root2;
	cin>>u>>v;
	Root1=Find(S,u-1);
	Root2=Find(S,v-1);
	if(Root1==Root2)
		 cout<<"yes"<<endl;
	else cout<<"no"<<endl;
}
void Check_network(SetType S,int n)
{
	int i,counter=0;
	for(i=0;i<n;i++){
		if(S[i]==-1) counter++;
	}
	if(counter==1)
		cout<<"The network is connected."<<endl;
	else
		cout<<"There are "<<counter<<" components"<<endl;
}
void Initalization(SetType S,int N)
{
	for(int i=0;i<=N;i++)
	{
		S[i]=-1;
	}
}
int main()
{
	SetType S;
	int n;
	char in;
	cin>>n;
	Initalization(S,n);//初始化函数
	do
	{
		cin>>in;
		switch(in){
			case 'I':Input_connection(S);break;
			case 'C':Check_connection(S);break;
			case 'S':Check_network(S,n);break; 
		}	
	} while(in!='S');
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

June_gjy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值