二叉树
存储和权值比较
int h[N],ne[N*2],e[N*2],w[N],idx;
int dep[N];
void add(int x,int y ){
e[idx]=y,//当前节点的下一个节点序号
ne[idx]=h[x],//ne数组保存e数组对应位置的下一个节点所在的索引
h[x]=idx++;
}
void bfs(int x,int dep)//以深度为单位
{
maxn=max(dep,maxn);//记录整个二叉树的最大深度
d[dep]+=w[x];
for(int i=h[x];i!=-1;i=ne[i]){
int j=e[i];
dfs(j,dep+1);
}
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
for(int i=1;i<=n;i++){
if(2*i<=n){
add(i,2*i);
}
if(2*i+1<=n){
add(i,i*2+1);
}
}
dfs(1,1);
int res=1;
for(int i=2;i<=maxn;i++)//i遍历每层
{
if(d[i]>=d[res]){
res=i;
}
}
cout<<res<<endl;
return 0;
}
图中点的层次
临接表模板
图的存储:邻接表
用 h 数组保存各个节点能到的第一个节点的编号。(具体为多个head链表)
开始时,h[i] 全部为 -1。各个链表中都没有节点!
用 e 数组保存节点编号,ne 数组保存 e 数组对应位置的下一个节点所在的索引。
用 idx 保存下一个 e 数组中,可以放入节点位置的索引
插入边使用的头插法,例如插入:a->b。首先把b节点存入e数组,e[idx] = b。然后 b 节点的后继是h[a],ne[idx] = h[a]。最后,a 的后继更新为 b 节点的编号,h[a] = idx,索引指向下一个可以存储节点的位置,idx ++ 。
!!!idx有两种含义:
1.给每个新插入的节点的唯一标识符
2.表示当前邻接表中共有多少个节点
方法一:利用双指针和一个数组记录一个队列
int h[N],ne[N],e[N],idx;
int d[N],q[N];
void add(int x,int y ){
e[idx]=y,//当前节点的下一个节点序号
ne[idx]=h[x],
h[x]=idx++;
}
void bfs()
{
int hh=0,tt=0;//双指针记录一个队列
q[0]=1;//存储一个队列
memset(d,-1,sizeof d);//记录是否走过
d[0]=1;//d数组里存储的是边的长度
while(hh<=tt)
{
int t=q[hh++];
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(d[j]==-1){
d[j]=d[i]+1;
q[tt++]=j;
}
}
} return d[n];
}
方法二:利用stl记录一个队列
int h[N],ne[N],e[N],idx;
int st[N],dis[N];
void add(int x,int y ){
e[idx]=y,//当前节点的下一个节点序号
ne[idx]=h[x],//ne数组保存e数组对应位置的下一个节点所在的索引
h[x]=idx++;
}
void bfs()
{
memset(dist,-1,sizeof dist);
dist[0]=1;
queue<int > q;
q.push(1);
st[1]=1;
while(!q.empty()){
int t=q.front();
q.pop();
for(int i=h[i];i!=-1;i=ne[i]){
int j=e[i];
while(!st[j]){
dis[j]=dis[i]+1;
st[j]=1;//节点入队
q.push(j);
}
}
}
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
add(a,b);
}
bfs();
cout<<dis[n]<<endl;
return 0;
}
特殊二叉树 堆排序
具体性质
o(n)的插入方法
void down(int u) {
int t=u;
if(u*2<=n&&h[u*2]<h[u])t=u*2;
if(u*2+1<=n&&h[u*2+1]<h[u])t=u*2+1;
if(u!=t) {
swap(h[u],h[t]);
down(t);//递归 再down t的子节点
}
}
int main() {
int n;
cin>>n;
for(int i=1; i<=n; i++) {
scanf("%d",&h[i]);
}
int size=n;
for(int i=n/2; i; i--)down(i);
while(m--) { //把最小的元素删掉
cout<<h[1]<<endl;//处理根节点方便
h[1]=h[size];
size--;
down(1);
}
return 0;
}