《算法笔记》——数据结构

数据结构


并查集

int p[N];//p[1]=2意思是节点1的父亲是2,祖宗节点的父节点设置为自身,即p[x]=x
int v[N];//可以存储每个集合的值
v[find(i)]=1;//i结点所在集合值为1
int find(int x)
{
	if(p[x]!=x)return p[x]=find(p[x]);
	return p[x];
}
//***初始化
for(int i=1;i<=n;i++)p[i]=i;
//***合并x和y
p[find(x)]=find(y);
//***判断是否在一个集合
find(x)==find(y);
//***最后可以执行下面代码进行最终路径压缩
for(int i=1;i<=n;i++)int t=find(i);
//***通过并查集求解连通块数量
for(int i=1;i<=n;i++)p[i]=i;
int cnt=n;//初始连通块数量为结点个数
if(find(a)!=find(b))
{
    p[find(a)]=find(b);
    cnt--;//连通块数量减一
}
//***定义边结构体存储边,然后循环每条边进行合并集合操作
int m//边数
struct e
{
    int a,b;
}
for(int i=0;i<m;i++)
{
    int a=e[i].a,b=e[i].b;
    int pa=p[a],pb=p[b];
    if(pa!=pb)pa=pb;//根据边联通节点
}
//***判断树中有无环
//不断插入有向边a->b
int root1 = find(a), root2 = find(b);
if (root1 != root2) s[root2] = root1;
else flag = false;//说明两个点已经在一个集合了,再插入边就会出现环(回路)

单链表

//head  表示头结点的下标
//e[i]  表示结点i的值
//ne[i] 表示结点i的next指针是多少
//idx   存储当前已经用到了哪个点
//-1    表示空结点
int head,e[N],ne[N].idx;
/*********初始化*********/
void init()
{
    head=-1;
    idx=0;
}
/*********将x插到头结点*********/
void add_to_head(int x)
{
    e[idx]=x;
    ne[idx]=head;
    head=idx;
    idx++;
}
/*********将x插到下标为k的点后面*********/
void add(int x,int k)
{
    e[idx]=x;
    ne[idx]=ne[k];
    ne[k]=idx;
    idx++;
}
/*********将下标为k的后面的点删除*********/
void remove(int k)
{
    ne[k]=ne[ne[k]];
}
/*********输出链表*********/
for(int i=head;i!=-1;i=ne[i])cout<<e[i];

双链表

int e[N],l[N],r[N],idx;
void init()
{
//0表示左端点,1表示右端点
	r[0]=1;
	l[1]=0;
	idx=2;
}
//在下标为k的点的右边插入x
void add(int k,int k)
{
    e[idx]=x;
    r[idx]=r[k];
    l[idx]=k;
    l[r[k]]=idx;
    r[k]=idx;
}
//删除第k个点
void remove(int k)
{
    r[l[k]]=r[k];
	l[r[k]]=l[k];        
}

邻接表/树

int h[N];//存储每个头结点
int e[M],ne[M],idx;//存储结点的值和next指针
int w[M];//存储边的权值
void init()//初始化邻接表
{
    memset(h,-1,sizeof(h));
}
void add(int a,int b,int t)//插入从a到b的边,且边权为t
{
	e[idx]=b;
    ne[idx]=h[a];
    w[idx]=t;
    h[a]=idx++;
}
for (int i = h[u]; ~i; i = ne[i])//遍历一个节点的所有边
    dfs(e[i], depth + 1);
for(int i=0;i<idx;i++)
    int a=e[i^1],b=e[i];// 对于无向图,取出方向相反的一对边,因为每次加边都是成对添加,相反方向的两个边编号的奇偶有特殊关系 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值