数据结构的合并

引言

有一类经典的数据结构问题,要求高效地支持以下几种操作:

1.新建一个数据结构

2.将两个数据结构的信息合并(要求合并操作满足交换律、结合律)

3.在数据结构中查询某些信息

这类问题有时需要根据数据结构的特性设计操作,同时也存在一类较为通用的解决方法。

合并操作可以看做批量地在数据结构中添加信息,而一般的插入操作则是合并的特例

定义与约定

设n表示问题中新建的数据结构个数

|A|表示数据结构A由几个数据结构合并得到

A+B表示合并A,B得到的数据结构,因此有|A+B|=|A|+|B|

直接合并

当合并两个数据结构时,可以将其中一个数据结构的信息逐一插入到另一个数据结构中,总共需要进行O(n^2)次插入操作。

基于某些特殊性质的合并

森林实现的并查集可以直接通过修改父亲合并

无旋转treap可以基于分裂操作递归合并,若两树值域区间不相交也可以用类似斜堆的合并方式

各种可并堆也设计了相应的方式进行高效的合并

此类合并一般非常高效,一部分还能同时在非均摊的意义下保证很低的合并复杂度,但一般难以推广。

启发式合并

若在合并A,B时,令|A|<=|B|,将A拆散并逐一插入B,由于每次插入会使一个元素所在数据结构增大至少一倍,可以将插入操作的次数降至O(nlogn)。

平衡树启发式合并是一个常见的例子。

基于相同结构的合并

对于两个结构相同的数据结构,可以考虑将两个数据结构重叠起来,合并重叠部分的信息。

一个简单的例子是trie的合并,将两棵待合并的trie重叠起来,从根开始dfs求出重叠部分并合并相关信息。合并的时间复杂度与合并时重叠部分的大小有关,由于重叠部分合并后总点数减少了,可以保证总的时间复杂度与合并时减少的点数同阶。

对于线段树或k-d树,如果采用相同的区间划分方式,也可以使数据结构的结构相同,从而可以应用这个方法。

此方法一般优于直接进行启发式合并。

例题 2014年集训队互测 bzoj3615 MSS

题目大意 维护一些平面上的点集,支持按某一维坐标分割点集,合并两个点集,对一个点集的所有点点权加上一个数,询问一个点集的点权和、最小/大值。

对给出的点建立二维k-d树,建树后将每个点到根的路径提取出来得到n棵只包含一个点的相同结构的k-d树。合并操作可以很方便地递归进行,点权的维护可以仿照线段树打标记实现。分裂操作可以看作合并的逆操作,由于k-d树的结构,可以保证分裂时增加点数为O(n^(1/2))。

基于二进制分组的合并

某些时候,不能高效地在数据结构中插入一条信息,这时候便很难应用前文所提及的方法。如果对A+B的一次查询可以转化为对A,B分别查询,那么可以平衡合并和查询的时间复杂度,在合并时不完全合并,以增加查询的复杂度为代价减少合并次数。

对于数据结构A,可以将|A|表示为一些互不相同的2的非负整数次幂之和(至多分为O(log|A|)个数),并将信息分别维护,查询时在O(log|A|)个部分内分别查询。在合并时,仿照二进制加法的进位过程,合并对应的部分。这样一个元素每参与一次合并,所在数据结构的大小增大一倍,若合并A,B的时间复杂度为O(|A|+|B|),则合并操作的总时间复杂度为O(nlogn),优于直接对二进制分组套用启发式合并。

时间: 2024-09-28 07:01:03

数据结构的合并的相关文章

数据结构例程——合并有序表

本文针对数据结构基础系列网络课程(2):线性表中第15课时有序表. 问题:有两个有序表LA和LB,将它们合并成一个有序表LC.要求不破坏原有表LA和LB 算法思想: 解法1:用顺序表实现(支持的算法库,及list.h文件,请点击链接-) #include "list.h" void UnionList(SqList *LA,SqList *LB,SqList *&LC) { int i=0,j=0,k=0; //i.j.k分别作为LA.LB.LC的下标 LC=(SqList *

数据结构 - 启发式合并

定义:将两个数据结构合并时,应将小的数据结构中的元素一个一个分别插入大的数据结构. 顺便写了一道“简单”题 ——梦幻布丁 (可坑死我了是我太弱了) 现在回过头来这道题真的不难,我只是栽到以前挖的坑里去了(链表没学好) 这告诉我们一个道理 —— 千万不要边走边挖坑啊,有坑赶紧填! 我jio得这篇代码注释真的很良心(因为几乎没有人给这么简单的代码标注释) 好了...... 笔者叨叨叨正式结束   颜色一定是单调不增,段数一定是单调不增的,可以一边修改一边 ans-- 用链表维护每一个颜色的下标,启发

数据结构 Merge合并排序

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int[] a = { 1, 5, 7, 12 }; int[] b = { 2, 6, 8, 9 };

浅谈算法和数据结构

: 一 栈和队列 http://www.cnblogs.com/yangecnu/p/Introduction-Stack-and-Queue.html 最近晚上在家里看Algorithems,4th Edition,我买的英文版,觉得这本书写的比较浅显易懂,而且“图码并茂”,趁着这次机会打算好好学习做做笔记,这样也会印象深刻,这也是写这一系列文章的原因.另外普林斯顿大学在Coursera 上也有这本书同步的公开课,还有另外一门算法分析课,这门课程的作者也是这本书的作者,两门课都挺不错的. 计算

数据结构基础温故-7.排序

排序(Sorting)是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为按关键字“有序”的记录序列.如何进行排序,特别是高效率地进行排序时计算机工作者学习和研究的重要课题之一.排序有内部排序和外部排序之分,若整个排序过程不需要访问外存便能完成,则称此类排序为内部排序,反之则为外部排序.本篇主要介绍插入排序.交换排序.选择排序和归并排序这几种内部排序方法. 首先,我们今天的目标就是编写一个SortingHelper类,它是一个提供了多种排序方法的帮助类,后面我们的目标就是实现其中

浅谈算法和数据结构系列汇总(转)

突然看到一个大神的系列文章讲的就是算法和数据结构,现在把它的文章集中分享给大家,向大神致敬: 浅谈算法和数据结构: 一 栈和队列 浅谈算法和数据结构: 二 基本排序算法 浅谈算法和数据结构: 三 合并排序 浅谈算法和数据结构: 四 快速排序 浅谈算法和数据结构: 五 优先级队列与堆排序 浅谈算法和数据结构: 六 符号表及其基本实现 浅谈算法和数据结构: 七 二叉查找树 浅谈算法和数据结构: 八 平衡查找树之2-3树 浅谈算法和数据结构: 九 平衡查找树之红黑树 浅谈算法和数据结构: 十 平衡查找

ruby reduce方法

Ruby 中一些好用的方法(注意reduce方法) 2016-07-27 17:57 370人阅读 评论(0) 收藏 举报 #####inject inject是我使用最频繁的方法了,它的强大之处在于可以方便的对嵌套的数组,哈希等混合数据结构进行合并或求和, 可以有效减少代码量. 例如最常见的数组套哈希: 1 2 3 4 array = [{a:100}, {b:200}, {c:300}] array.inject(0) { |sum, e| sum += e.values.first } #

《R语言实战》读书笔记(一)

以下全为个人理解,若不全面,你打我啊! 首先,本书分成三个部分: 第一:数据的操作.(第二.四.五.十五章) 分为数据结构(合并与重塑),变量或观测(创建,修改,删除,重命名,选取),特殊值的处理(缺失值处理),以及一般函数. 第二:图形的绘制.(第三.六.十一章) 分为一维变量,二维变量,三维及多为变量的可视化.每一种又分为定性变量和定量变量两种类型. 第三:数据分析.(第七到十章以及十二到十四章) 基础分析(即频数/位置/分布等), 关联性分析(独立性与相关性), 差异性分析(样本与总体.两

种类并查集

//http://acm.timus.ru/problem.aspx?space=1&num=1003//分析:树和递归最常用的思想是分治:并查集是一种合并树的数据结构:合并树或加入树节点时,我们只在意新建立的树边上相邻的两个树节点之间的关系,实际上树边只在意相邻两个树节点之间的关系//思路:可以讲一段连续区间的奇偶性表示成两个前缀和的奇偶性:将出现的离散的点用map离散化一下:将数量减少的点做一次种类并查集 1 #include"iostream" 2 #include&qu