首页 > 其他分享 >[学习笔记] 动态开点权值线段树合并 - 数据结构

[学习笔记] 动态开点权值线段树合并 - 数据结构

时间:2024-07-03 19:20:54浏览次数:17  
标签:rt 数据结构 return rs int ls 权值 开点 id

权值线段树

例题

【模板】普通平衡树

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 1;
int n, val[N], opt[N], num[N], cnt, len, san[N], m[N], rnk[N];
unordered_map<int, int> dfn;
struct WeightedSegmentTree{
	#define ls (id << 1)
	#define rs (id << 1 | 1)
	struct node{ int l, r, num; }t[N<<2];
	inline void pushup(int id){ t[id].num = t[ls].num + t[rs].num; }
	inline void build(int id, int l, int r){
		t[id].l = l, t[id].r = r;
		if(l == r) return;
		int mid = (l + r) >> 1;
		build(ls, l, mid), build(rs, mid+1, r);
	}
	inline void modify(int id, int u, int v){
		if(t[id].l == t[id].r) return (void)(t[id].num += v);
		int mid = (t[id].l + t[id].r) >> 1;
		modify(u<=mid?ls:rs, u, v);
		pushup(id);
	}
	inline int query_rank(int id, int th){
		if(t[id].l == t[id].r) return rnk[t[id].l];
		if(th <= t[ls].num) return query_rank(ls, th);
		else return query_rank(rs, th-t[ls].num);	
	}
	inline int query_minnum(int id, int u){
		if(t[id].l == t[id].r) return 1; // output the smallest rank
		int mid = (t[id].l + t[id].r) >> 1;
		if(u <= mid) return query_minnum(ls, u);
		else return query_minnum(rs, u) + t[ls].num;
	}
	inline int query_maxnum(int id, int u){
		if(t[id].l == t[id].r) return t[id].num; // output the biggest rank
		int mid = (t[id].l + t[id].r) >> 1;
		if(u <= mid) return query_maxnum(ls, u);
		else return query_maxnum(rs, u) + t[ls].num;
	}
	inline int query_nxt(int id, int u){
		return query_rank(1, query_minnum(1, u)-1);
	}
	inline int query_lst(int id, int u){
		return query_rank(1, query_maxnum(1, u)+1);
	}
}WST;
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>n;
	for(int i=1, op; i<=n; ++i){
		cin>>op;
		opt[i] = op, cin>>num[i];
		if(op != 4 && op != 2)
			val[++cnt] = num[i], san[cnt] = m[cnt] = val[cnt];
	}
	// 以下为离散化
	sort(m+1, m+1+cnt);
	len = unique(m+1, m+1+cnt) - (m+1);
	for(int i=1; i<=cnt; ++i){
		san[i] = lower_bound(m+1, m+1+len, san[i]) - m;
		dfn[val[i]] = san[i], rnk[san[i]] = val[i];
	}
	WST.build(1, 1, cnt);
	for(int i=1; i<=n; ++i){
		switch(opt[i]){
			case 1: WST.modify(1, dfn[num[i]], 1); break;
			case 2: WST.modify(1, dfn[num[i]], -1); break;
			case 3: cout<<WST.query_minnum(1, dfn[num[i]])<<'\n'; break;
			case 4: cout<<WST.query_rank(1, num[i])<<'\n'; break;
			case 5: cout<<WST.query_nxt(1, dfn[num[i]])<<'\n'; break;
			case 6: cout<<WST.query_lst(1, dfn[num[i]])<<'\n'; break;
		}
	} return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 1;
int n, m, f[N], rt[N], q, rnk[N];
inline int find(int k){
	if(!f[k]) return k;
	return f[k] = find(f[k]); 
}
struct WeightedSegmentTree{
	int ls[N<<6], rs[N<<6], sum[N<<6], cnt;
	inline void pushup(int id){ sum[id] = sum[ls[id]] + sum[rs[id]]; }
	inline void modify(int& id, int l, int r, int u){
		if(!id) id = ++cnt;
		if(l == r) return (void)(sum[id] = 1);
		int mid = (l + r) >> 1;
		if(u <= mid) modify(ls[id], l, mid, u);
		else modify(rs[id], mid+1, r, u);
		pushup(id);
	}
	inline int query(int id, int l, int r, int rk){
		if(rk > sum[id]) return -1;
		if(l == r) return rnk[l];
		int mid = (l + r) >> 1;
		if(rk <= sum[ls[id]]) return query(ls[id], l, mid, rk);
		else return query(rs[id], mid+1, r, rk-sum[ls[id]]);
	}
	inline int merge(int a, int b, int l, int r){
		if(!a && !b) return 0;
		if(!a) return b; if(!b) return a;
		if(l == r) return a;
		int mid = (l + r) >> 1;
		ls[a] = merge(ls[a], ls[b], l, mid);
		rs[a] = merge(rs[a], rs[b], mid+1, r);
		pushup(a);
		return a;
	}
}MST;
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>n>>m;
	for(int i=1, val; i<=n; ++i){
		cin>>val, rnk[val] = i;
		MST.modify(rt[i], 1, n, val);
	}
	for(int i=1, a, b; i<=m; ++i){
		cin>>a>>b;
		a = find(a), b = find(b);
//		cout<<a<<' '<<b<<'\n';
		rt[b] = MST.merge(rt[a], rt[b], 1, n);
		f[b] = a;
	}
//	for(int i=1; i<=n; ++i) cout<<rt[i]<<' '; printf("\n"); 
//	printf("%d", rt[find(2)]);
//	return 0;
	cin>>q; char opt;
	for(int i=1, a, b; i<=q; ++i){
		cin>>opt>>a>>b;
		if(opt == 'Q') cout<<MST.query(rt[find(a)], 1, n, b)<<'\n';
		else{
			a = find(a), b = find(b);
			if(a == b) continue;
			f[b] = a;
			rt[a] = MST.merge(rt[a], rt[b], 1, n);
		}
	} return 0;
}

[Vani有约会] 雨天的尾巴

考虑对每个点进行动态开点权值线段树。对于树链修改,采用树上差分,最后把每个节点的子树和自己合并起来就是最终答案(树上差分不会可以看我博客)。注意,需要特判这个节点的最大救济粮数量,如果数量为 0,那么救济粮编号也为 0。

#include<bits/stdc++.h>
using namespace std;
#define min(x,y) (dfn[x] < dfn[y]) ? x : y
constexpr int N = 1e5 + 1;
int n, m, rt[N], dcnt, st[N][21], dfn[N], ans[N];
struct WeightedSegmentTree{
	#define tls t[id].ls
	#define trs t[id].rs
	int cnt;
	struct node{ int ls, rs, mx; }t[N<<6];
	inline void pushup(int id){ t[id].mx = max(t[tls].mx, t[trs].mx); }
	inline void modify(int& id, int l, int r, int u, int k){
		if(!id) id = ++cnt;
		if(l == r) return (void)(t[id].mx += k);
		int mid = (l + r) >> 1;
		if(u <= mid) modify(tls, l, mid, u, k);
		else modify(trs, mid+1, r, u, k);
		pushup(id);
	}
	inline int query(int id, int l, int r){
		if(!id) return 0;
		if(l == r){
			if(t[id].mx == 0) return 0; // spj!!!
			else return l;
		} 
		int mid = (l + r) >> 1;
		if(t[tls].mx >= t[trs].mx) return query(tls, l, mid);
		else return query(trs, mid+1, r);
	}
	inline int merge(int a, int b, int l, int r){
		if(!a || !b) return a+b;
		if(l == r){ t[a].mx += t[b].mx; return a; }
		int mid = (l + r) >> 1;
		t[a].ls = merge(t[a].ls, t[b].ls, l, mid);
		t[a].rs = merge(t[a].rs, t[b].rs, mid+1, r);
		pushup(a);
		return a;
	}
}MST;
vector<int> G[N];
inline void dfs1(int u, int f){
	st[dfn[u] = ++dcnt][0] = f;
	for(int v : G[u]) if(!dfn[v]) dfs1(v, u);
}
inline int Lca(int u, int v){
	if(u == v) return u;
	if((u = dfn[u]) > (v = dfn[v])) swap(u, v);
	int k = __lg(v - u++);
	return min(st[u][k], st[v-(1<<k)+1][k]);
}
bitset<N> vis;
inline void dfs2(int u){
	vis[u] = 1;
	for(int v : G[u])
		if(!vis[v]) dfs2(v), rt[u] = MST.merge(rt[u], rt[v], 1, N);
	ans[u] = MST.query(rt[u], 1, N); // 注意必须这时候统计答案
}
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>n>>m;
	for(int i=1, a, b; i<n; ++i){
		cin>>a>>b;
		G[a].push_back(b), G[b].push_back(a);
	}
	dfs1(1, 0);
	for(int j=1; j<=__lg(n); ++j)
		for(int i=1; i<=n-(1<<j)+1; ++i)
			st[i][j] = min(st[i][j-1], st[i+(1<<(j-1))][j-1]);
	for(int i=1, a, b, c, lca; i<=m; ++i){
		cin>>a>>b>>c; lca = Lca(a, b);
		MST.modify(rt[a], 1, N, c, 1);
		MST.modify(rt[b], 1, N, c, 1);
		MST.modify(rt[lca], 1, N, c, -1);
		MST.modify(rt[st[dfn[lca]][0]], 1, N, c, -1);
	}
	dfs2(1);
	for(int i=1; i<=n; ++i) cout<<ans[i]<<'\n';
	return 0;
}

蒟蒻的数列

服了,想复杂了。刚开始时在 modify 的同时统计 sum,于是就乱了。这道题需要动态开点维护 lazy_tag,最后再统计 sum 就非常简单了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
constexpr int N = 1e7 + 1, MAX = 1e9;
int n, rt;
struct SegmentTree{
	int ls[N], rs[N], tag[N], cnt;
	inline void addtag(int& id, int v){ if(!id) id = ++cnt; tag[id] = max(tag[id], v); }
	inline void pushdown(int id){ if(tag[id]) addtag(ls[id], tag[id]), addtag(rs[id], tag[id]); tag[id] = 0; }
	inline void modify(int& id, int x, int y, int l, int r, int k){
		if(!id) id = ++cnt;
		if(l <= x && y <= r){ addtag(id, k); return; }
		pushdown(id);
		int mid = (x + y) >> 1;
		if(l <= mid) modify(ls[id], x, mid, l, r, k);
		if(r > mid ) modify(rs[id], mid+1, y, l, r, k);
	}
	inline int query(int id, int l, int r){
		if(!ls[id] && !rs[id]) return tag[id]*(r-l+1);
		pushdown(id);
		int mid = (l + r) >> 1, ans = 0;
		if(ls[id]) ans += query(ls[id], l, mid);
		if(rs[id]) ans += query(rs[id], mid+1, r);
		return ans;
	}
}ST;
signed main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>n;
	for(int i=1, a, b, c; i<=n; ++i){
		cin>>a>>b>>c;
		if(a <= b-1) ST.modify(rt, 1, MAX, a, b-1, c);
	}
	return cout<<ST.query(1, 1, MAX), 0;
}

[NOIP2016 提高组] 天天爱跑步

集树上差分与线段树合并一体的好题!看题解看的

首先,我们只需要记录这个点在某个时间点上有没有人即可,权值线段树即可解决。但是又有新的问题:这需要沿着某条树链 \(0:+1\),\(1:+1\),\(2:+1\) 等等,无法差分,并且最后合并的时候子节点的时间数据会加到父节点上,这是错误的。

可以发现,随着时间的推移,节点的深度也在随之变化,那么就可以把时间信息与深度挂钩。对于 \(u -> lca\) 的节点,把他们的 \(dep[u]:+1\);对于 \(lca -> u\) 的节点,把他们的 \(dep[lca]*2-dep[a]:+1\),最后统计的时候统计每个节点的 \(dep[u]+val[u]\) 和 \(dep[u]-val[u]\) 的权值即可。最后注意判断 \(val[u]\) 是否等于 0,若等于 0,ans 就会加两次。

#include<bits/stdc++.h>
using namespace std;
constexpr int N = 3e5, M = 6e5;
int n, m, val[N], fa[N], size[N], son[N], dep[N], rt[N], ans[N], top[N];
vector<int> G[N];
inline void dfs1(int u){
	size[u] = 1, son[u] = -1;
	for(int v : G[u]){
		if(!dep[v]){
			dep[v] = dep[fa[v]=u] + 1;
			dfs1(v);
			size[u] += size[v];
			if(son[u] == -1 || size[v] > size[son[u]]) son[u] = v;
		}
	}
}
inline void dfs2(int u, int t){
	top[u] = t;
	if(son[u] == -1) return;
	dfs2(son[u], t);
	for(int v : G[u]) if(v != son[u] && v != fa[u]) dfs2(v, v);
}
inline int Lca(int u, int v){
	int tu = top[u], tv = top[v];
	while(tu != tv){
		if(dep[tu] > dep[tv]) tu = top[u=fa[tu]];
		else tv = top[v=fa[tv]];
	} return dep[u]>dep[v]?v:u;
}
struct WeightedSegmentTree{
	int ls[N<<5], rs[N<<5], sum[N<<5], cnt;
	inline void modify(int &id, int l, int r, int u, int k){
		if(!id) id = ++cnt;
		if(l == r) return (void)(sum[id] += k);
		int mid = (l + r) >> 1;
		if(u <= mid) modify(ls[id], l, mid, u, k);
		else modify(rs[id], mid+1, r, u, k);
	}
	inline int query(int id, int l, int r, int u){
		if(!id) return 0;
		if(l == r) return sum[id];
		int mid = (l + r) >> 1;
		if(u <= mid) return query(ls[id], l, mid, u);
		else return query(rs[id], mid+1, r, u);
	}
	inline int merge(int a, int b, int l, int r){
		if(!a || !b) return a+b;
		if(l == r){ sum[a] += sum[b]; return a; }
		int mid = (l + r) >> 1;
		ls[a] = merge(ls[a], ls[b], l, mid);
		rs[a] = merge(rs[a], rs[b], mid+1, r);
		sum[a] = sum[ls[a]] + sum[rs[a]];
		return a;
	}
}WST;
bitset<N> vis;
inline void dfs(int u){
	vis[u] = 1;
	for(int v : G[u])
		if(!vis[v]) dfs(v), rt[u] = WST.merge(rt[u], rt[v], 1, M<<1);
	if(val[u]) ans[u] += WST.query(rt[u], 1, M<<1, dep[u]+val[u]+M);
	ans[u] += WST.query(rt[u], 1, M<<1, dep[u]-val[u]+M);
}
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>n>>m;
	for(int i=1, a, b; i<n; ++i) cin>>a>>b, G[a].push_back(b), G[b].push_back(a);
	for(int i=1; i<=n; ++i) cin>>val[i];
	dep[1] = 1, dfs1(1); dfs2(1, 1);
	for(int i=1, a, b, lca; i<=m; ++i){
		cin>>a>>b; lca = Lca(a, b);
		WST.modify(rt[a], 1, M<<1, dep[a]+M, 1);
		WST.modify(rt[fa[lca]], 1, M<<1, dep[a]+M, -1);
		WST.modify(rt[b], 1, M<<1, dep[lca]*2-dep[a]+M, 1);
		WST.modify(rt[lca], 1, M<<1, dep[lca]*2-dep[a]+M, -1);
	} dfs(1);
	for(int i=1; i<=n; ++i) cout<<ans[i]<<' ';
	return 0;
}

[USACO17JAN] Promotion Counting P

不说了,板子。

#include<bits/stdc++.h>
using namespace std;
constexpr int N = 1e5 + 1, M = 9e6 + 1, MAX = 1e9+1;
int n, rt[N], ans[N], val[N];
vector<int> G[N];
struct WeightedSegmentTree{
	int cnt, ls[M], rs[M], sum[M];
	inline void modify(int &id, int l, int r, int u){
		if(!id) id = ++cnt;
		if(l == r) return (void)(++sum[id]);
		int mid = (l + r) >> 1;
		if(u <= mid) modify(ls[id], l, mid, u);
		else modify(rs[id], mid+1, r, u);
		sum[id] = sum[ls[id]] + sum[rs[id]];
	}
	inline int query(int id, int l, int r, int u){
		if(!id) return 0;
		if(l == r) return sum[id];
		int mid = (l + r) >> 1, ans = 0;
		if(u <= mid) ans += sum[rs[id]] + query(ls[id], l, mid, u);
		else ans += query(rs[id], mid+1, r, u);
		return ans;
	}
	inline int merge(int a, int b, int l, int r){
		if(!a || !b) return a+b;
		if(l == r){ sum[a] += sum[b]; return a; }
		int mid = (l + r) >> 1;
		ls[a] = merge(ls[a], ls[b], l, mid);
		rs[a] = merge(rs[a], rs[b], mid+1, r);
		sum[a] = sum[ls[a]] + sum[rs[a]];
		return a;
	}
}WST;
bitset<N> vis;
inline void dfs(int u){
	vis[u] = 1;
	for(int v : G[u]) if(!vis[v]) dfs(v), rt[u] = WST.merge(rt[u], rt[v], 1, MAX);
	ans[u] = WST.query(rt[u], 1, MAX, val[u]+1);
}
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>n;
	for(int i=1; i<=n; ++i) cin>>val[i], WST.modify(rt[i], 1, MAX, val[i]);
	for(int i=2, a; i<=n; ++i) cin>>a, G[i].push_back(a), G[a].push_back(i);
	dfs(1); for(int i=1; i<=n; ++i) cout<<ans[i]<<'\n'; return 0;
}

魔法少女LJJ

\(c<=7\)

好恶心啊,调了我一晚上 + 一下午

对于需要维护 tag 的动态开点线段树,对于这道题了来说,涉及区间修改的只有 把某一区间修改为 0。所以不开点不打 tag 不影响接续的修改,所以没开过的点就不要打 tag 了,会 T。另外开过的点一定打 tag。对于合并操作,不要试图维护 tag,直接 pushdown 即可。

#include<bits/stdc++.h>
using namespace std;
constexpr int N = 4e5 + 1, M = 1e7 + 1, MAX = 1e9 + 1;
int m, tot, num[N], rt[N], f[N];
inline int find(int k){
	if(!f[k]) return k;
	return f[k] = find(f[k]);
}
struct WeightedSegmentTree{
	int ls[M], rs[M], sum[M], cnt=1;
	double mul[M]; bitset<M> tag;
	inline void addtag(int &id){
		tag[id] = 0; sum[id] = mul[id] = 0;
	}
	inline void pushdown(int id){
		if(!tag[id]) addtag(ls[id]), addtag(rs[id]);
		tag[id] = 1;
	}
	inline void pushup(int id){
		sum[id] = sum[ls[id]] + sum[rs[id]];
		mul[id] = mul[ls[id]] + mul[rs[id]];
	}
	inline void modify_itv(int &id, int x, int y, int l, int r){
		if(l > r || !id) return; //因为修改为0,所以不开点不打tag不影响接续的修改 
		if(l <= x && y <= r) return (void)(addtag(id)); //开过的点一定打 tag
		int mid = (x + y) >> 1; pushdown(id);
		if(l <= mid) modify_itv(ls[id], x, mid, l, r);
		if(r >  mid) modify_itv(rs[id], mid+1, y, l, r);
		pushup(id);
	}
	inline void modify_nod(int &id, int l, int r, int u, int k){
		if(!id) id = ++cnt, tag[id] = 1;
		if(l == r) return (void)(sum[id]+=k, mul[id]+=log(u)*k);
		int mid = (l + r) >> 1; pushdown(id); 
		if(u <= mid) modify_nod(ls[id], l, mid, u, k);
		else modify_nod(rs[id], mid+1, r, u, k);
		pushup(id);
	}
	inline int query_rnk(int id, int l, int r, int k){
		if(!id || k > sum[id]) return 0;
		if(l == r) return l;
		int mid = (l + r) >> 1; pushdown(id);
		if(k <= sum[ls[id]]) return query_rnk(ls[id], l, mid, k);
		else return query_rnk(rs[id], mid+1, r, k-sum[ls[id]]);
	}
	inline int query_sum(int id, int x, int y, int l, int r){
		if(!id || l > r) return 0;
		if(l <= x && y <= r) return sum[id];
		int mid = (x + y) >> 1, ans = 0; pushdown(id);
		if(l <= mid) ans += query_sum(ls[id], x, mid, l, r);
		if(r >  mid) ans += query_sum(rs[id], mid+1, y, l, r);
		return ans;
	}
	inline int merge(int a, int b, int l, int r){
		if(!a || !b) return a+b; //²»ÒªºÏ²¢tag ûÓÐÓà 
		if(l == r){ sum[a] += sum[b]; return a; }
		int mid = (l + r) >> 1; pushdown(a), pushdown(b);
		sum[a] += sum[b], mul[a] += mul[b];
		ls[a] = merge(ls[a], ls[b], l, mid);
		rs[a] = merge(rs[a], rs[b], mid+1, r);
		return a;
	}
	inline void change_max(int &id, int u){
		int s = query_sum(id, 1, MAX, u+1, MAX);
		if(!s) return;
		modify_itv(id, 1, MAX, u+1, MAX);
		modify_nod(id, 1, MAX, u, s);
	}
	inline void change_min(int &id, int u){
		int s = query_sum(id, 1, MAX, 1, u-1);
		if(!s) return;
		modify_itv(id, 1, MAX, 1, u-1);
		modify_nod(id, 1, MAX, u, s);
	}
}WST;
int main(){
	ios::sync_with_stdio(0), cout.tie(0), cout.tie(0);
	cin>>m;
	for(int i=1, opt, a, b, fa, fb; i<=m; ++i){
		cin>>opt>>a;
		switch(opt){
			case 1:
				num[++tot] = 1; WST.modify_nod(rt[tot], 1, MAX, a, 1); break;
			case 2:
				cin>>b; fa = find(a), fb = find(b); if(fa == fb) break;
				f[fb] = fa; rt[fa] = WST.merge(rt[fa], rt[fb], 1, MAX);
				num[fa] += num[fb]; break;
			case 3:
				cin>>b; WST.change_min(rt[find(a)], b); break;
			case 4:
				cin>>b; WST.change_max(rt[find(a)], b); break;
			case 5:
				cin>>b; fa = find(a); if(b > num[fa]){ cout<<"0\n"; break; }
				cout<<WST.query_rnk(rt[fa], 1, MAX, b)<<'\n'; break;
			case 6:
				cin>>b; fa = find(a), fb = find(b);
				if(fa == fb){ cout<<"0\n"; break; }
				cout<<(WST.mul[rt[fa]]>WST.mul[rt[fb]]?1:0)<<'\n'; break;
			default: cout<<num[find(a)]<<'\n';
		}
	} return 0;
}

标签:rt,数据结构,return,rs,int,ls,权值,开点,id
From: https://www.cnblogs.com/xiaolemc/p/18270399

相关文章

  • 高效存储的秘诀:bitmap 数据结构在标签中的应用
    在当今大数据和信息爆炸的时代,如何有效地管理和查询海量的数据成为了企业和开发者面临的重大挑战。其中,标签系统作为数据管理中的一种重要手段,被广泛应用于用户画像、商品分类、内容推荐等多个场景。然而,随着标签数量的急剧增加,传统的数据存储和查询方式已难以满足高效率、低延迟......
  • 数据结构小学期第三天
    今天试着完成第二阶段的目标,实现九宫格拼图游戏,但是看着教程只有4*4的我也只能先按照这个做了APP.class1importcom.itheima.ui.GameJFrame;2importcom.itheima.ui.LoginJFrame;3importcom.itheima.ui.RegisterJFrame;45publicclassApp{6publicstat......
  • 【数据结构】堆栈
    目录一、堆栈的基本概念1.1堆栈定义1.2堆栈操作1.3堆栈应用二、顺序栈2.1定义2.2操作2.3C语言实现三、共享栈3.1定义3.2操作3.3C语言实现四、链式栈4.1定义4.2操作4.3C语言实现五、总结        堆栈(Stack)重要的数据结构,它们在计算机科......
  • 数据结构第3节: 抽象数据类型
    第3节:基础概念-抽象数据类型(ADT)抽象数据类型(ADT)是一种逻辑上的数学模型,以及定义在此数学模型上的一组操作。ADT通常隐藏了底层实现的细节,只暴露出一个可以被外界访问和操作的接口。在Java中,ADT可以通过接口(interface)来定义,并通过类(class)来实现。2.3.1抽象数据类型的定......
  • 【408考点之数据结构】B树和B+树
    B树和B+树在大规模数据存储和检索中,B树和B+树是两种广泛使用的数据结构。它们被设计用来高效地管理数据,使得插入、删除和查找操作都能在对数时间内完成。以下是对这两种数据结构的详细介绍。1.B树(B-Tree)定义:B树是一种自平衡的多路查找树,通常用于数据库和文件系统中。B树......
  • [JLU] 数据结构与算法上机题解思路分享-第三次上机
    前言首先,请务必自己尽全力尝试实现题目,直接看成品代码,思维就被拘束了,也很容易被查重。这里只是思路解析的博客,代码仓库在JLU_Data_Structures_Record希望你能在这里找到你想要的:)正文A图的创建分数10作者朱允刚单位吉林大学请编写程序创建一个有向图。有向图中包含......
  • 数据结构小学期第2天
    今日完成了小组分发的剩下两个题目其一,老板的作息表新浪微博上有人发了某老板的作息时间表,表示其每天4:30就起床了。但立刻有眼尖的网友问:这时间表不完整啊,早上九点到下午一点干啥了?本题就请你编写程序,检查任意一张时间表,找出其中没写出来的时间段。输入格式:输入第一行给出......
  • PART1-Oracle关系数据结构
    2.Oracle关系数据结构2.1.表和表簇2.1.1.模式对象简介数据库模式是数据结构的逻辑容器,这些数据结构称为模式对象。模式对象的例子有表和索引。模式对象是通过SQL创建和操作的。一个数据库用户拥有密码和各种数据库权限。每个用户拥有一个与其同名的模式。模式包含了属于......
  • [JLU] 数据结构与算法上机题解思路分享-第二次上机
    前言首先,请务必自己尽全力尝试实现题目,直接看成品代码,思维就被拘束了,也很容易被查重。这里只是思路解析的博客,代码仓库在JLU_Data_Structures_Record希望你能在这里找到你想要的:)正文A二叉树的创建与遍历分数10作者朱允刚单位吉林大学通过带空指针信息的先根序列(......
  • 数据结构:期末考 第六次测试(总复习)
    一、单选题(共50题,100分)1、表长为n的顺序存储的线性表,当在任何位置上插入或删除一个元素的概率相等时,插入一个元素所需移动元素的平均个数为(D).(2.0)A、(n−1)/2B、nC、n+1D、n/22、设栈S和队列Q的初始状态为空,元素e1、e2、e3、e4、e5和e6依次通过栈S,一个元素出栈后......