具体实施方式
下面结合附图,对本说明书披露的多个实施例进行描述。
本说明书实施例中提供一种用于存储有向图的链式存储结构(以下将该结构统称为十字双向链表),以及对该存储结构中的数据记录进行删除的方法。下面,首先对所述方法的发明构思和应用场景进行介绍。
一个有向图D是一个二元组,即D=<V,E>,其中V是一个非空集合,称为D的顶点集(vertex),V中的元素称为顶点。E为D的边集,为笛卡尔积VxV的多重子集,其元素为有向边,简称边。具体地,用有序对<a,b>表示顶点a指向顶点b的边。对于图1中示出的有向图,其对应的顶点集V和边集E分别为:V={V0,V1,V2,V3},E={<V0,V1>,<V0,V2>,<V2,V0>,<V2,V3>,<V3,V0>,<V3,V1>,<V3,V2>}。
而十字链表(Orthogonal List)是有向图的一种链式存储结构。在十字链表存储结构中,包括对顶点的存储和对边的存储。具体地,一条数据记录对应一个顶点或一条边,以下将顶点对应的数据记录称为顶点记录,将边对应的数据记录称为边记录。在一个例子中,如图2所示,顶点记录包括三个数据项,分别对应存储有:顶点的具体数据信息(data),指向以该顶点为终点的第一条边的逆向后继指针,以及指向以该顶点为起点的第一条边的正向后继指针。在一个具体的例子中,与有向图中多个顶点对应的多个顶点记录构成数组xList[num]。在一个例子中,如图3所示,边记录包括4个数据项,分别对应存储有边的起点,边的终点,指向具有相同终点的下一条边的逆向后继指针,以及指向具有相同起点的下一条边的正向后继指针。进一步地,其中前两个数据项具体可以为边的起点在顶点数组xList[num]中的位置,以及边的终点在顶点数组xList[num]中的位置。
从十字链表的数据结构来看,有向图中的每一个顶点对应一个逆向链表和一个正向链表。其中,逆向链表包括具有相同终点的边记录,图4中示出与图1中的有向图对应的十字链表,以顶点V2为例,通过沿着V2的逆向后继指针和各个边记录的逆向后继指针,可以确定出与顶点V2对应的逆向链表,该逆向链表(图4中通过图例I标识)包括边记录E2和E7。而正向链表包括具有相同起点的边记录,以顶点V2为例,通过沿着V2的正向后继指针和各个边记录的正向后继指针,可以确定出与顶点V2对应的正向链表,该正向链表(图4中通过图例Ⅱ标识)包括边记录E3和E4。
发明人发现,当需要删除有向图中的顶点或边时,需要采用遍历链表的方式,在十字链表中删除对应的顶点记录和/或边记录。具体地,在一种情况下,当需要删除有向图中的边时,则需要遍历链表以对该条边对应的边记录进行查找、标记和删除。在另一种情况下,当需要删除有向图中的顶点时,则需要从顶点数组中删除该顶点所对应的顶点记录,同时,通过遍历链表的方式,对该顶点记录对应的边记录进行查找、标记和删除。
在一个例子中,假定需要对图4中的边记录E2进行删除,在定位到E2以后,因其中只包括逆向后继指针和正向后继指针,故而只能获知E2在逆向链表中的下一记录和在正向链表中的下一记录,因此直接删除E2会导致链表中断,所以需要先对E2进行标记,然后通过从V2开始遍历逆向链表的方式,确定E2在逆向链表中的上一记录,以及,通过从V0开始遍历正向链表的方式,确定E2在正向链表中的上一记录。再完成对E2的删除。显然,通过遍历链表的方式完成记录的删除,将耗费大量的计算资源。
基于以上观察和统计,发明人提出一种用于存储有向图的链式存储结构,具体地,对十字链表进行了改进,如图5所示,在其中边记录原有的四个数据项的基础上增加两个数据项,分别对应于指向具有相同终点的上一条边的逆向前驱指针和指向具有相同起点的上一条边的正向前驱指针。由此在需要对边记录进行删除时,在定位到该边记录以后,可以据该边记录中包括四个指针:正向前驱指针、正向后继指针、逆向前驱指针、逆向后继指针,获知该边记录在正向链路中的上一记录和下一记录,以及在逆向链路中的上一记录和下一记录,进而直接完成对该边记录的删除。如此,在定位到待删除的边记录以后,可以直接完成删除,而无需遍历链表,从而节省了计算资源。下面,描述以上过程的具体实施步骤。
本说明书披露的存储方法,用于对有向图进行存储,其中有向图包括多个顶点和至少一条有向边。具体地,基于发明人提出的存储结构,即十字双向链表,将每个顶点对应存储成一条顶点记录,将每条有向边对应存储成一条边记录。下面,以存储有向图中的第一有向边为例,进行示例性说明,需要说明的是,上述第一有向边可以为有向图中的任一条边。
具体地,图6示出根据一个实施例的基于十字双向链表存储有向图的方法,所述方法的执行主体可以为具有处理能力的装置或设备,如服务器。如图6所示,所述方法包括以下步骤:步骤S610,获取作为第一有向边起点的第一顶点,并将第一顶点存储为第一边记录的第一数据项;步骤S620,获取作为第一有向边终点的第二顶点,并将第二顶点存储为第一边记录的第二数据项;步骤S630,获取第一正向信息集,其中包括顺序排列的多个信息项,分别记录第一顶点,以及以第一顶点为起点的至少一条边;步骤S640,获取第二逆向信息集,其中包括顺序排列的多个信息项,分别记录第二顶点,以及以第二顶点为终点的至少一条边;步骤S650,确定第一有向边的逆向后继指针,逆向后继指针指向第一有向边在第二逆向信息集中的下一个信息项,并将逆向后继指针存储为第一边记录的第三数据项;步骤S660,确定第一有向边的正向后继指针,正向后继指针指向第一有向边在第一正向信息集中的下一个信息项,并将正向后继指针存储为第一边记录的第四数据项;步骤S670,确定第一有向边的逆向前驱指针,逆向前驱指针指向第一有向边在第二逆向信息集中的上一个信息项,并将逆向前驱指针存储为第一边记录的第五数据项;步骤S680,确定第一有向边的正向前驱指针,正向前驱指针指向第一有向边在第一正向信息集中的上一个信息项,并将正向前驱指针存储为第一边记录的第六数据项。以上步骤具体如下:
首先,在步骤S610,获取作为第一有向边起点的第一顶点,并将第一顶点存储为第一边记录的第一数据项。以及,在步骤S620,获取作为第一有向边终点的第二顶点,并将第二顶点存储为第一边记录的第二数据项。
在一个实施例中,可以获取第一顶点的相关信息,并将此相关信息存储为第一数据项。在一个具体的实施例中,相关信息可以包括第一顶点的名称。在另一个具体的实施例中,第一顶点对应第一顶点记录,相应地,在一个例子中,相关信息可以包括第一顶点记录对应的变量名。在另一个例子中,有向图中顶点集对应的多个顶点记录构成顶点数组,此时,相关信息可以包括第一顶点记录在顶点数组中的位置。
在另一个实施例中,可以获取第二顶点的相关信息,并将此相关信息存储为第二数据项。需要说明的是,其中关于第二顶点的相关信息的描述,可以参见前述对于第一顶点的相关信息的描述,在此不作赘述。
以上,可以确定出第一边记录中的第一数据项和第二数据项(可参见图7)。接着,在步骤S630,获取第一正向信息集,其中包括顺序排列的多个信息项,分别记录第一顶点,以及以第一顶点为起点的至少一条边。以及,在在步骤S640,获取第二逆向信息集,其中包括顺序排列的多个信息项,分别记录第二顶点,以及以第二顶点为终点的至少一条边。
下面,首先对正向信息集和逆向信息集进行说明。在一个实施例中,可以基于有向图包括的顶点集和边集,确定与顶点集中各个顶点对应的正向信息集和逆向信息集。
以第一顶点为例,对于第一顶点对应的逆向信息集的确定,在一个具体的实施例中,可以从顶点集中获取第一顶点,并确定记录第一顶点的信息项,以及从边集中确定以第一顶点为终点的至少一条边,并确定其中各条边所对应的信息项,然后基于预设规则对确定出的多个信息项进行排序,再将得到的顺序排列的多个信息项组成与第一顶点对应的第一逆向信息集。进一步地,在一个例子中,其中对多个信息项进行排序可以包括:将多个信息项中记录第一顶点的信息项排在首位,再根据边集中多条边的总的排列顺序(以下将总的排列顺序简称为总排序),将多个信息项中其他记录各条边的信息项进行对照排序。
更进一步地,在一个具体的例子中,其中边集中多条边的总排序,可以基于对多条边的随机排列而确定。在另一个具体的例子中,其中边集中多条边的总排序,可以采用如下方法:首先对顶点集中的顶点进行顺序编号,例如,由小到大的编号,然后,确定多条边中各条边的起点和终点的编号,对于起点编号不同的两条边,将起点编号小的边排在起点编号大的边之前,而对于起点编号相同的两条边,将终点编号小的边排在终点编号小的边之前。如此,可以确定出边集中多条边的总排序,再进一步地,在一个更具体的例子中,对于图1中由小到大编号的顶点V0,V1,V2和V3,可以确定出边集中多条边的总排序如图8所示。
另一方面,对于第一顶点对应的正向信息集的确定,在一个具体的实施例中,在确定记录第一顶点的信息项后,还可以从边集中确定以第一顶点为起点的至少一条边,并确定其中各条边所对应的信息项,然后基于预设规则将确定出的多个信息项进行排序,再将得到的顺序排列的多个信息项组成与第一顶点对应的第一正向信息集。在一个的例子中,其中对多个信息项进行排序可以包括:将多个信息项中记录第一顶点的信息项排在首位,再根据边集中多条边的总排序,将多个信息项中其他记录各条边的信息项进行对照排序。需要说明的是,此处提到的边集中多条边的总排序与前述实施例中提到的总排序一致。也就是说,可以预先确定边集中多条边的总排序,如此,在之后确定各顶点对应的正向信息集和逆向信息集的过程中,可以直接使用已确定的总排序。
根据一个具体的例子,基于图1中示出的有向图的顶点集和边集,以及图8中示出的对于边集中多条边的总排序,可以确定出图9中示出的与顶点集中各个顶点对应的逆向信息集和正向信息集。需要说明的是,图9中以表格的形式示出逆向信息集和正向信息集,实际还可以为其他形式,如序列形式,对于信息集的表达形式,在此不作限定。
在一个实施例中,正向信息集可以基于邻接表直接获得,逆向信息集可以基于逆邻接表直接获得。
在另一个实施例中,正向信息集和逆向信息集还可以基于编程人员的输入而直接获取。
以上,可以确定出有向图中各个顶点所对应的逆向信息集和正向信息集。
进一步地,在一个实施例中,基于以上预先确定出的与各个顶点对应的逆向信息集和正向信息集,可以获取与第一有向边的起点,即第一顶点,所对应的第一正向信息集,以及,获取与第一有向边的终点,即第二顶点,所对应的第二逆向信息集。在一个例子中,假定第一有向边为<V2,V0>,则第一顶点为V2,第二顶点为V0,基于图9,可以获取第一正向信息集,包括顺序排列的信息项V2、<V2,V0>和<V2,V3>,以及获取第二逆向信息集,包括顺序排列的信息项V0、<V2,V0>和<V3,V0>。
另一方面,在另一个实施例中,也可以不预先确定出与各个顶点对应的逆向信息集和正向信息集,而是在获取作为第一有向边起点的第一顶点,和获取作为第一有向边终点的第二顶点以后,再基于上述实施例中的相关步骤,确定出对应的第一正向信息集和第二逆向信息集。
由上,在步骤S610和步骤S620中可以确定出第一边记录的第一数据项和第二数据项,以及,在步骤S630和步骤S640中可以获取第一正向信息集和第二逆向信息集。然后,可以基于获取的两个信息集,确定第一边记录的第三数据项、第四数据项、第五数据项和第六数据项,具体如下:
一方面,在步骤S650,确定第一有向边的逆向后继指针,逆向后继指针指向第一有向边在第二逆向信息集中的下一个信息项,并将逆向后继指针存储为第一边记录的第三数据项。以及,在步骤S660,确定第一有向边的正向后继指针,正向后继指针指向第一有向边在第一正向信息集中的下一个信息项,并将正向后继指针存储为第一边记录的第四数据项。
在一个实施例中,确定第一有向边的逆向后继指针可以包括:确定第一有向边在第二逆向信息集中的下一个信息项(以下将此信息项称为信息项A),进而确定指向信息项A的指针,再将此指针作为逆向后继指针存储为第一边记录的第三数据项。
需要说明的是,其中指向信息项A,即指向信息项A所对应的数据记录,或者说,即指向信息项A所对应的内存地址。进一步地,在一个具体的实施例中,在获取信息项A以后,可以建立信息项A对应的数据记录A,然后创建指向数据记录A的逆向后继指针,并将其存储为第三数据项。在一个例子中,基于图9,假定第一有向边为<V2,V0>,则对应的信息项A为<V3,V0>,由此可以确定指向<V3,V0>的指针,并将此指针作为第一边记录的第三数据项,具体如图10所示,其中从逆向后继指针起始的箭头,表示该指针指向的是数据记录A。
此外,在一个具体的实施例中,当第一有向边在第一逆向信息集中的下一个信息项为空,也就是,第一有向边在第一逆向信息集中不存在下一个信息项时,可以将逆向后继指针确定为空指针。在一个例子中,基于图9,假定第一有向边为<V2,V3>,则其在对应的逆向信息集中的下一个信息项为空值,由此,可以将其对应的逆向后继指针确定为空指针,具体可以表示为^。
在一个实施例中,确定第一有向边的正向后继指针可以包括:确定第一有向边在第一正向信息集中的下一个信息项(以下将此信息项称为信息项B),进而确定指向信息项B的指针,再将此指针作为正向后继指针存储为第一边记录的第四数据项。在一个例子中,基于图9,假定第一有向边为<V2,V0>,则对应的信息项B为<V2,V3>,由此可以确定指向<V2,V3>的指针,并将此指针作为第一边记录的第四数据项,具体如图11所示,其中从正向后继指针起始的箭头,表示该指针指向的是数据记录B。此外,在一个具体的实施例中,当第一有向边在第一正向信息集中的下一个信息项为空时,可以将正向后继指针确定为空指针,相关描述可以参见前述实施例,在此不作赘述。
以上可以确定第三数据项和第四数据项,另一方面,在步骤S670,确定第一有向边的逆向前驱指针,逆向前驱指针指向第一有向边在第二逆向信息集中的上一个信息项,并将逆向前驱指针存储为第一边记录的第五数据项。以及,在步骤S680,确定第一有向边的正向前驱指针,正向前驱指针指向第一有向边在第一正向信息集中的上一个信息项,并将正向前驱指针存储为第一边记录的第六数据项。
在一个实施例中,确定第一有向边的逆向前驱指针可以包括:确定第一有向边在第二逆向信息集中的上一个信息项(以下将此信息项称为信息项C),进而确定指向信息项C的指针,再将此指针作为逆向前驱指针存储为第一边记录的第五数据项。在一个例子中,基于图9,假定第一有向边为<V2,V0>,则对应的信息项C记录顶点V0,由此可以确定指向V0的指针,并将此指针作为第一边记录的第五数据项,具体如图12所示,其中从逆向前驱指针起始的箭头,表示该指针指向的是数据记录C。需要说明的是,数据记录C属于顶点记录,关于顶点记录的创建将在后文中进行介绍。
在一个实施例中,确定第一有向边的正向前驱指针可以包括:确定第一有向边在第一正向信息集中的上一个信息项(以下将此信息项称为信息项D),进而确定指向信息项D的指针,再将此指针作为正向前驱指针存储为第一边记录的第六数据项。在一个例子中,基于图9,假定第一有向边为<V2,V0>,则对应的信息项D记录顶点V2,由此可以确定指向V2的指针,并将此指针作为第一边记录的第六数据项,具体如图13所示,其中从正向前驱指针起始的箭头,表示该指针指向的是数据记录D。
由此,可以确定出第一边记录中的第五数据项和第六数据项。
综上,可以确定出第一边记录中的第一数据项、第二数据项、第三数据项、第四数据项、第五数据项和第六数据项。在一个实施例中,第一边记录可以由这六个数据项构成。在另一个实施例中,第一边记录中还可以包括其他数据项,例如,存储有第一有向边的权重信息的数据项。需要说明的是,边记录中各个数据项的相对位置可以与图7中示出的相同,也可以不同,对此不作限定。
以上,对十字双向链表中边记录的确定方法进行了介绍。下面,再对顶点记录的确定方法进行说明。具体以存储有向图中的第一顶点为例,进行示例性说明,需要说明的是,上述第一顶点可以为有向图中的任意一个顶点。
具体地,在一种实施方式中,如图14所示,顶点记录的确定方法可以包括以下步骤:
首先,在步骤S141,获取第一顶点的顶点数据,并将顶点数据存储为第一顶点记录的第一数据项。
在一个实施例中,从顶点集中获取第一顶点,并确定第一顶点的顶点数据。其中,顶点数据可以包括顶点所对应的参数名称、参数内容和参数类型,等等。进一步地,可以将顶点数据存储为第一顶点记录的第一数据项。在一个例子中,假定获取的第一顶点为图1中的顶点V1,且对应的顶点数据为参数名称V1,则可以将“V1”作为第一顶点记录的第一数据项进行存储。
以上,可以确定第一顶点数据记录的第一数据项。接着,在步骤S142,获取第一逆向信息集,其中包括顺序排列的多个信息项,分别记录所述第一顶点,以及以所述第一顶点为终点的至少一条边。以及,在步骤S143,获取第一正向信息集,其中包括顺序排列的多个信息项,分别记录所述第一顶点,以及以所述第一顶点为起点的至少一条边。
需要说明的是,对于第一逆向信息集和第一正向信息集的获取,可以参见上文中的相关描述,在此不作赘述。
在获取第一逆向信息集以后,然后,在步骤S144,确定第一顶点的逆向后继指针,逆向后继指针指向第一顶点在第一逆向信息集中的下一个信息项,并将逆向后继指针存储为第一顶点记录的第二数据项。以及,在步骤S145,确定第一顶点的正向后继指针,正向后继指针指向第一顶点在第一正向信息集中的下一个信息项,并将正向后继指针存储为第一顶点记录的第三数据项。
在一个实施例中,其中确定第一顶点的逆向后继指针可以包括:确定第一有向边在第一逆向信息集中的下一个信息项(以下将此信息项称为信息项M),进而确定指向信息项M的指针,再将此指针作为逆向后继指针存储为第一边记录的第二数据项。进一步地,在一个具体的实施例中,当第一顶点在第一逆向信息集中的下一个信息项为空时,可以将逆向后继指针确定为空指针。在一个例子中,基于图9,假定第一顶点为V1,则可以确定其对应的信息项M为<V0,V1>,由此可以确定指向<V0,V1>的指针,并将此指针作为第一顶点记录的第二数据项,具体如图15所示,其中从逆向后继指针起始的箭头,表示该指针指向的是数据记录M。
在一个实施例中,其中确定第一顶点的正向后继指针可以包括:确定第一有向边在第一正向信息集中的下一个信息项(以下将此信息项称为信息项N),进而确定指向信息项N的指针,再将此指针作为正向后继指针存储为第一边记录的第三数据项。进一步地,在一个具体的实施例中,当第一顶点在第一正向信息集中的下一个信息项为空时,可以将正向后继指针确定为空指针。在一个例子中,基于图9,假定第一顶点为V1,则可以确定其对应的信息项N为空,由此,可以将其对应的正向后继指针确定为空指针,如图15所示,具体可以表示为^。
由此,可以确定出第一顶点记录中的第二数据项和第三数据项。
综上,可以确定出第一顶点记录中的第一数据项、第二数据项、第三数据项。在一个实施例中,第一顶点记录可以由这三个数据项构成。在另一个实施例中,第一边记录中还可以包括其他数据项。
基于以上实施例中提供的基于十字双向链表存储有向图的方法。在一个具体的例子中,对于图1中示出的有向图,可以将其存储为图16中示出的十字双向链表。其中,用虚线框标识出了相对于图4中的十字链表,新增的两个数据项,即逆向前驱指针和正向前驱指针。以及,用于虚线箭头标识出了对应指针所指向的数据记录。
基于以上实施例中描述的用于存储有向图的十字双向链表,根据另一方面的实施例,还提供一种十字双向链表中边记录的删除方法。下面,以第一边记录为例,进行示例性说明,需要说明的是,上述第一边记录可以为十字双向链表中的任一条边记录。
具体地,图17示出根据一个实施例的十字双向链表中边记录的删除方法。如图17所示,所述方法具体包括以下步骤:步骤S1710,确定十字双向链表中待删除的第一边记录;步骤S1720,基于第一边记录中的第一逆向前驱指针,确定第一逆向前驱指针所指向的第二数据记录;步骤S1730,基于第一边记录中的第一逆向后继指针,确定第一逆向后继指针所指向的第三数据记录;步骤S1740,将第二数据记录中的第二逆向后继指针由指向第一边记录修改为指向第三数据记录;步骤S1750,基于第一边记录中的第一正向前驱指针,确定第一正向前驱指针所指向的第四数据记录;步骤S1760,基于第一边记录中的第一正向后继指针,确定第一正向后继指针所指向的第五数据记录;步骤S1770,将第四数据记录中的第四正向后继指针由指向第一边记录修改为指向第五数据记录。
首先,在步骤S1710,确定十字双向链表中待删除的第一边记录。
在一个实施例中,可以根据接收到的针对第一边记录的删除指令,定位到第一边记录。在一个具体的实施例中,可以根据删除指令中包括的与第一边记录对应的变量名,定位到第一边记录。
在一个实施例中,如图7所示,第一边记录中包括对应的第一逆向后继指针,第一正向后继指针,第一逆向前驱指针和第一正向前驱指针。
在以上定位到第一边记录之后,接着在步骤S1720,基于第一边记录中的第一逆向前驱指针,确定第一逆向前驱指针所指向的第二数据记录。
在一个实施例中,第二数据记录可以为边记录或顶点记录。在一个例子中,基于图16,假定第一边记录为e1,可以确定第二数据记录是与顶点V1对应的顶点记录。在另一个例子中,假定第一边记录为e4,可以确定第二数据记录是与顶点V3对应的顶点记录。
在以上确定第二数据记录以后,接着在步骤S1730,基于第一边记录中的第一逆向后继指针,确定第一逆向后继指针所指向的第三数据记录。
在一个实施例中,第三数据记录可以为空记录。在一个例子中,基于图16,假定第一边记录为e4,由此可以判断出e4中的逆向后继指针是空指针,也就是e4所指向的第三数据记录为空。
在另一个实施例中,第三数据记录可以不是空记录。在一个例子中,基于图16,假定第一边记录为e1,由此可以判断出e1中的逆向后继指针所指向的第三数据记录为e6。
在以上确定第三数据记录以后,接着在步骤S1740,将第二数据记录中的第二逆向后继指针由指向第一边记录修改为指向第三数据记录。
在一个实施例中,第三数据记录为空。相应地,可以将第二逆向后继指针修改为空指针。在一个例子中,基于图16,假定第一边记录为e4,由此可以判断出对应的第三数据记录为空,相应地,可以将对应第二数据记录,即与顶点V3对应的顶点记录,中的逆向后继指针修改为空指针,且修改后的十字双向链表如图18所示。
在另一个实施例中,第三数据记录不为空。相应地,可以将第二逆向后继指针由指向第一边记录修改为指向非空的第三数据记录。进一步地,还可以将第三数据记录中的第三逆向前驱指针由指向第一边记录修改为指向第二数据记录。在一个例子中,基于图16,假定第一边记录为e1,由此可以确定出其逆向后继指针所指向的第三数据记录为e6。由此,将对应的第二数据记录,即与顶点V1对应的顶点记录,中的逆向后继指针由指向e1修改为指向e6。以及,将e6中的逆向前驱指针由指向e1修改为指向与顶点V1对应的顶点记录,且修改后的十字双向链表如图19所示。
再接着,在步骤S1750,基于第一边记录中的第一正向前驱指针,确定第一正向前驱指针所指向的第四数据记录。
在一个实施例中,第四数据记录可以为边记录或顶点记录。在一个例子中,基于图16,假定第一边记录为e1,可以确定第四数据记录是与顶点V0对应的顶点记录。在另一个例子中,基于图16,假定第一边记录为e4,可以确定第四数据记录是边记录e3。
在以上确定第四数据记录之后,接着在步骤S1760,基于第一边记录中的第一正向后继指针,确定第一正向后继指针所指向的第五数据记录。
在一个实施例中,第五数据记录为空记录。在一个例子中,基于图16,假定第一边记录为e4,由此可以确定e4的正向后继指针是空指针,也就是第五数据记录为空记录。
在一个实施例中,第五数据记录为非空记录。在一个例子中,基于图16,假定第一边记录为e1,由此可以确定e1的正向后继指针所指向的第五数据记录为e2。
在以上确定第五数据记录之后,接着在步骤S1770,将第四数据记录中的第四正向后继指针由指向第一边记录修改为指向第五数据记录。
在一个实施例中,第五数据记录为空记录。相应地,可以将第四正向后继指针修改为空指针。在一个例子中,基于图18,假定第一边记录为e4,由此可以确定出e4的正向后继指针所指向的第五数据记录为空。此外,第四数据记录是边记录e3,由此可以将e3中的正向后继指针修改为空指针,基于图18修改后的十字双向链表如图20所示。如此,因不存在指向第一边记录e4的指针,从而实现了对e4的删除。
在另一个实施例中,第五数据记录为非空记录。相应地,可以将第四正向后继指针由指向第一边记录修改为指向非空的第五数据记录,进一步地,还可以将第五数据记录中的第五正向前驱指针由指向第一边记录修改为指向第四数据记录。在一个例子中,基于图19,假定第一边记录为e1,由此可以确定出其正向后继指针所指向的第五数据记录为e2。进一步地,第四数据记录是与顶点V0对应的顶点记录,由此将其中的正向后继指针由指向e1修改为指向e2。以及,将e2中的正向前驱指针由指向e1修改为指向与顶点V0对应的顶点记录。基于图19修改后的十字双向链表如图21所示。如此,因不存在指向第一边记录e1的指针,从而实现了对e1的删除。
由上可知,基于本说明书实施例提供的十字双向链表的存储结构,在需要对边记录进行删除时,在定位到该边记录以后,可以据该边记录中包括四个指针:正向前驱指针、正向后继指针、逆向前驱指针、逆向后继指针,获知该边记录在正向链路中的上一记录和下一记录,以及在逆向链路中的上一记录和下一记录,进而直接完成对该边记录的删除。如此,在定位到待删除的边记录以后,可以直接完成删除,而无需遍历链表,从而节省了计算资源。
根据另一方面的实施例,还提供一种十字双向链表中顶点记录的删除方法。在一个实施例中,所述方法包括,首先,确定待删除的顶点记录,然后沿着与该顶点记录对应的正向链路确定待删除的第一部分的边记录,以及沿着与该顶点记录对应的逆向链路确定待删除的第二部分的边记录。进一步地,可以对待删除的顶点记录进行删除,以及基于上述实施例中描述的对边记录的删除方法,对上述第一部分和第二部分对应的各个边记录进行删除。
根据另一方面的实施例,还提供一种存储有向图的装置,所述有向图包括多个顶点和至少一条有向边,每个顶点对应一条顶点记录,每个有向边对应一条边记录,所述至少一条有向边包括第一有向边。图22示出根据一个实施例的基于十字双向链表存储有向图的装置。如图22所示,所述装置2200包括:
第一获取单元2201,配置为获取作为所述第一有向边起点的第一顶点。
第一存储单元2202,配置为将所述第一顶点存储为第一边记录的第一数据项。
第二获取单元2203,配置为获取作为所述第一有向边终点的第二顶点。
第二存储单元2204,配置为将所述第二顶点存储为所述第一边记录的第二数据项。
第三获取单元2205,配置为获取第一正向信息集,其中包括顺序排列的多个信息项,分别记录所述第一顶点,以及以所述第一顶点为起点的至少一条边。
第四获取单元2206,配置为获取第二逆向信息集,其中包括顺序排列的多个信息项,分别记录所述第二顶点,以及以所述第二顶点为终点的至少一条边。
第一确定单元2207,配置为确定所述第一有向边的逆向后继指针,所述逆向后继指针指向所述第一有向边在所述第二逆向信息集中的下一个信息项。
第三存储单元2208,配置为将所述逆向后继指针存储为所述第一边记录的第三数据项。
第二确定单元2209,配置为确定所述第一有向边的正向后继指针,所述正向后继指针指向所述第一有向边在所述第一正向信息集中的下一个信息项。
第四存储单元2210,配置为将所述正向后继指针存储为所述第一边记录的第四数据项。
第三确定单元2211,配置为确定所述第一有向边的逆向前驱指针,所述逆向前驱指针指向所述第一有向边在所述第二逆向信息集中的上一个信息项。
第五存储单元2212,配置为将所述逆向前驱指针存储为所述第一边记录的第五数据项。
第四确定单元2213,配置为确定所述第一有向边的正向前驱指针,所述正向前驱指针指向所述第一有向边在所述第一正向信息集中的上一个信息项。
第六存储单元2214,配置为将所述正向前驱指针存储为所述第一边记录的第六数据项。
在一个实施例中,所述第一确定单元2207具体配置为:当所述第一有向边在所述第二逆向信息集中的下一个信息项为空时,将所述逆向后继指针确定为空指针;所述第二确定单元2209具体配置为:当所述第一有向边在所述第一正向信息集中的下一个信息项为空时,将所述正向后继指针确定为空指针。
在一个实施例中,所述第三确定单元2211具体配置为:当所述第一有向边在所述第二逆向信息集中的上一个信息项为第二顶点时,将所述逆向前驱指针指向所述第二顶点对应的顶点记录;当所述第一有向边在所述第二逆向信息集中的上一个信息项为第二有向边时,将所述逆向前驱指针指向所述第二有向边对应的边记录。
在一个实施例中,所述确第四确定单元2213具体配置为:当所述第一有向边在所述第一正向信息集中的上一个信息项为第三顶点时,将所述正向前驱指针指向所述第三顶点对应的顶点记录;当所述第一有向边在所述第一正向信息集中的上一个信息项为第三有向边时,将所述正向前驱指针指向所述第三有向边对应的边记录。
在一个实施例中,所述装置还包括:第五获取单元,配置为获取所述第一顶点的顶点数据。第七存储单元,配置为将所述顶点数据存储为第一顶点记录的第一数据项。第六获取单元,配置为获取第一逆向信息集,其中包括顺序排列的多个信息项,分别记录所述第一顶点,以及以所述第一顶点为终点的至少一条边。第五确定单元,配置为确定所述第一顶点的逆向后继指针,所述第一顶点的逆向后继指针指向所述第一顶点在所述第一逆向信息集中的下一个信息项。第八存储单元,配置为将所述第一顶点的逆向后继指针存储为第一顶点记录的第二数据项。第六确定单元,配置为确定所述第一顶点的正向后继指针,所述第一顶点的正向后继指针指向所述第一顶点在所述第一正向信息集中的下一个信息项。第九存储单元,配置为将所述第一顶点的正向后继指针存储为第一顶点记录的第三数据项。
进一步地,在一个具体的实施例中,所述第五确定单元具体配置为:当所述第一顶点在所述第一逆向信息集中的下一个信息项为空时,将所述第一顶点的逆向后继指针确定为空指针;所述第六确定单元具体配置为:当所述第一顶点在所述第一正向信息集中的下一个信息项为空时,将所述第一顶点的正向后继指针确定为空指针。
根据再一方面的实施例,还提供一种十字双向链表中边记录的删除装置,所述十字双向链表包括多条数据记录,所述多条数据记录包括顶点记录和边记录,所述顶点记录至少包括对应顶点的逆向后继指针和正向后继指针,所述边记录至少包括,对应边的逆向前驱指针、逆向后继指针、正向前驱指针和正向后继指针。图23示出根据一个实施例的十字双向链表中边记录的删除装置结构图,所述装置2300包括:
第一确定单元2301,配置为确定所述十字双向链表中待删除的第一边记录;
第二确定单元2302,配置为基于所述第一边记录中的第一逆向前驱指针,确定所述第一逆向前驱指针所指向的第二数据记录;
第三确定单元2303,配置为基于所述第一边记录中的第一逆向后继指针,确定所述第一逆向后继指针所指向的第三数据记录;
第一修改单元2304,配置为将所述第二数据记录中的第二逆向后继指针由指向第一边记录修改为指向所述第三数据记录;
第四确定单元2305,配置为基于所述第一边记录中的第一正向前驱指针,确定所述第一正向前驱指针所指向的第四数据记录;
第五确定单元2306,配置为基于所述第一边记录中的第一正向后继指针,确定所述第一正向后继指针所指向的第五数据记录;
第二修改单元2307,配置为将所述第四数据记录中的第四正向后继指针由指向第一边记录修改为指向第五数据记录。
在一个实施例中,所述第三数据记录为空,所述第一修改单元2304具体配置为:将所述第二逆向后继指针由指向第一边记录修改为空指针。
在一个实施例中,所述第三数据记录不为空,所述装置2300还包括:第三修改单元,配置为将所述第三数据记录中的第三逆向前驱指针由指向第一边记录修改为指向第二数据记录。
在一个实施例中,所述第五数据记录为空,所述第二修改单元2307配置为:将所述第四逆向后继指针由指向第一边记录修改为空指针。
在一个实施例中,所述第五数据记录不为空,所述装置还包括:第四修改单元,配置为将所述第五数据记录中的第五正向前驱指针由指向第一边记录修改为指向所述第四数据记录。
根据还一方面的实施例,还提供一种十字双向链表中顶点记录的删除装置,所述十字双向链表包括多条数据记录,所述多条数据记录包括顶点记录和边记录,所述顶点记录至少包括对应顶点的逆向后继指针和正向后继指针,所述边记录至少包括,对应边的逆向前驱指针、逆向后继指针、正向前驱指针和正向后继指针。所述装置可以包括:
第一确定单元,配置为确定所述十字双向链表中待删除的第一顶点记录;
第二配置单元,配置为确定与所述第一顶点记录对应的至少一条边记录;
删除单元,配置为删除所述第一顶点记录,以及基于以上任一实施例中描述的删除边记录的方法对所述至少一条边记录中的各条边记录进行删除。
如上,根据再一方面的实施例,还提供一种计算机可读存储介质,其上存储有计算机程序,当所述计算机程序在计算机中执行时,令计算机执行结合图6、或图14、或图17所描述的方法。
根据再一方面的实施例,还提供一种计算设备,包括存储器和处理器,所述存储器中存储有可执行代码,所述处理器执行所述可执行代码时,实现结合图6、或图14、或图17所描述的方法。
本领域技术人员应该可以意识到,在上述一个或多个示例中,本说明书披露的多个实施例所描述的功能可以用硬件、软件、固件或它们的任意组合来实现。当使用软件实现时,可以将这些功能存储在计算机可读介质中或者作为计算机可读介质上的一个或多个指令或代码进行传输。
以上所述的具体实施方式,对本说明书披露的多个实施例的目的、技术方案和有益效果进行了进一步详细说明,所应理解的是,以上所述仅为本说明书披露的多个实施例的具体实施方式而已,并不用于限定本说明书披露的多个实施例的保护范围,凡在本说明书披露的多个实施例的技术方案的基础之上,所做的任何修改、等同替换、改进等,均应包括在本说明书披露的多个实施例的保护范围之内。