一,堆
堆分为大顶堆和小顶堆
大顶堆每个结点比两个儿子大,小顶堆每个结点比两个儿子小
一般用完全二叉树储存堆
堆的表示
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;
}