SuperObject(Delphi最好的JSON简析类) 扩展功能----排序(4)最终揭秘 解决sosmAdd模式不能查找的问题

简介: 经过对代码的更深入的跟踪理解,发现了superobject采用的是平衡二叉树的方式保存数据的。   首先看看保存数据的类 TSuperAvlEntry = class   private     FGt, FLt: TSuperAvlEntry; FGt和FLt分别是保存通过比较(比较hash或者比较key的asc)大的保存在Gt,小的保存在Lt,是一个二叉树链表。

经过对代码的更深入的跟踪理解,发现了superobject采用的是平衡二叉树的方式保存数据的。

 

首先看看保存数据的类

TSuperAvlEntry = class
  private
    FGt, FLt: TSuperAvlEntry;

FGt和FLt分别是保存通过比较(比较hash或者比较key的asc)大的保存在Gt,小的保存在Lt,是一个二叉树链表。

 

先上图

2x

假如有如下Json

"assign": {
   "FAreaKey": "FKey",
   "FAreaName": "FName",
   "FAreaCode": "FCode",
}

按照sosmASC排序模式

1.首先插入的是FAreaKey节点,

2.然后插入的是FAreaName时跟Root就是FAreaKey进行比较那他会插入到FAreaKey对应的节点的Gt下图形A1表示

3.然后插入的是FAreaCode跟FAreakey比较时为较小的插入到LT下面如图A2表示

4.A2图已经为平衡二叉树。

 

再看看按sosmAdd排序模式

按照sosmAdd的模式的话都是排在后面也就是都放在GT位置

1.首先插入的是FAreaKey节点,

2.然后插入的是FAreaName时跟Root就是FAreaKey进行比较那他会插入到FAreaKey对应的节点的Gt下图形A1表示

3.然后插入的是FAreaCode跟FAreakey比较时因为GT位置已经有了FAreaName,此时再跟FAreaName比较也是为大的插入FAreaName的GT下面如图B1表示

4.如图B1表示经过平衡二叉树后变成了B2样式。

 

这样查找的话,因为sosmAdd的查询时都是查找GT位置,不会查找LT分支,所以查询FAreaKey时会查询不到。

所以简单的办法就是如果安装sosmAdd方式存储是不进行平衡二叉数,这样所有的数据都保存在GT位置。这样就成为了一个链表的方式,这样可以从头查到尾。必然可以查到。

 

*****深入研究后发现查询时之前的不区分Key的大小写的修改其实很容易做到。

 

最终的Insert代码为

function TSuperAvlTree.Insert(h: TSuperAvlEntry): TSuperAvlEntry;
var
  unbal, parentunbal, hh, parent: TSuperAvlEntry;
  depth, unbaldepth: longint;
  cmp: integer;
  unbalbf: integer;
  branch: TSuperAvlBitArray;
  p: Pointer;
begin
  inc(FCount);
  h.FLt := nil;
  h.FGt := nil;
  h.FBf := 0;
  branch := [];

  if (FRoot = nil) then
    FRoot := h
  else
  begin
    unbal := nil;
    parentunbal := nil;
    depth := 0;
    unbaldepth := 0;
    hh := FRoot;
    parent := nil;
    repeat
      if (hh.FBf <> 0) then
      begin
        unbal := hh;
        parentunbal := parent;
        unbaldepth := depth;
      end;
      if hh.FHash <> h.FHash then
      begin
        if nowSortMode = sosmDefault then
        begin
          //original code
          if hh.FHash < h.FHash then cmp := -1 else
            if hh.FHash > h.FHash then cmp := 1 else
              cmp := 0;
        end else
        begin
          // modify by mofen
          cmp := CompareForSortModeString(h.Name, hh.Name);
        end;

      end else
        cmp := CompareNodeNode(h, hh);
      if (cmp = 0) then
      begin
        Result := hh;
        //exchange data
        p := hh.Ptr;
        hh.FPtr := h.Ptr;
        h.FPtr := p;
        doDeleteEntry(h, false);
        dec(FCount);
        exit;
      end;
      parent := hh;
      if (cmp > 0) then
      begin
        hh := hh.FGt;
        include(branch, depth);
      end else
      begin
        hh := hh.FLt;
        exclude(branch, depth);
      end;
      inc(depth);
    until (hh = nil);

    if (cmp < 0) then
      parent.FLt := h else
      parent.FGt := h;

    depth := unbaldepth;

    if (unbal = nil) then
      hh := FRoot
    else
    begin
      if depth in branch then
        cmp := 1 else
        cmp := -1;
      inc(depth);
      unbalbf := unbal.FBf;
      if (cmp < 0) then
        dec(unbalbf) else
        inc(unbalbf);
      if cmp < 0 then
        hh := unbal.FLt else
        hh := unbal.FGt;
      if ((unbalbf <> -2) and (unbalbf <> 2)) then
      begin
        unbal.FBf := unbalbf;
        unbal := nil;
      end;
    end;

    if (hh <> nil) then
      while (h <> hh) do
      begin
        if depth in branch then
          cmp := 1 else
          cmp := -1;
        inc(depth);
        if (cmp < 0) then
        begin
          hh.FBf := -1;
          hh := hh.FLt;
        end else (* cmp > 0 *)
        begin
          hh.FBf := 1;
          hh := hh.FGt;
        end;
      end;


    //  original code
    //    if (unbal <> nil) then
    if (unbal <> nil) and (nowSortMode <> sosmAdd) then    //modify by mofen
    begin
      unbal := balance(unbal);
      if (parentunbal = nil) then
        FRoot := unbal
      else
      begin
        depth := unbaldepth - 1;
        if depth in branch then
          cmp := 1 else
          cmp := -1;
        if (cmp < 0) then
          parentunbal.FLt := unbal else
          parentunbal.FGt := unbal;
      end;
    end;
  end;
  result := h;
end;
目录
相关文章
|
6月前
|
JSON JavaScript 数据格式
jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能。
jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能。
152 1
|
12月前
|
Web App开发
chrome扩展:manifest.json文件相关字段
chrome扩展:manifest.json文件相关字段
56 0
|
12月前
|
存储 JSON 安全
Python中数据类转换为JSON的方法
Python中数据类转换为JSON的方法
151 0
|
20天前
|
JSON 数据格式
用来返回Json数据格式的工具--通用类
用来返回Json数据格式的工具--通用类
17 1
|
3月前
|
JSON 图形学 数据格式
Json☀️ 一、认识Json是如何解析成类的
Json☀️ 一、认识Json是如何解析成类的
|
4月前
|
存储 JSON 测试技术
python中json和类对象的相互转化
针对python中类对象和json的相关转化问题, 本文介绍了4种方式,涉及了三个非常强大的python库jsonpickle、attrs和cattrs、pydantic,但是这些库的功能并未涉及太深。在工作中,遇到实际的问题时,可以根据这几种方法,灵活选取。 再回到结构化测试数据的构造,当需要对数据进行建模时,也就是赋予数据业务含义,pydantic应该是首选,目前(2024.7.1)来看,pydantic的生态非常活跃,各种基于pydantic的工具也非常多,建议尝试。
|
5月前
|
JSON 关系型数据库 MySQL
理解和利用MySQL中的JSON功能
理解和利用MySQL中的JSON功能
158 2
|
5月前
|
JSON 关系型数据库 MySQL
实时计算 Flink版产品使用问题之在使用CDAS语法同步MySQL数据到Hologres时,如果开启了字段类型宽容模式,MySQL中的JSON类型会被转换为什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
4月前
|
JSON 数据格式
MysbatisPlus-核心功能-IService开发基础业务接口,MysbatisPlus_Restful风格,新增@RequestBody指定是为了接收Json数据的,使用swagger必须注解
MysbatisPlus-核心功能-IService开发基础业务接口,MysbatisPlus_Restful风格,新增@RequestBody指定是为了接收Json数据的,使用swagger必须注解
|
5月前
|
存储 JSON 关系型数据库
MySQL JSON 类型:功能与应用
MySQL JSON 类型:功能与应用