預排序樹 mysql 預排序樹實現無限極分類

2021-10-17 17:51:50 字數 4871 閱讀 6504

一.概念

左右值無限級分類,也稱為預排序樹無限級分類

是一種有序的樹狀結構

於這些樹狀結構中的每乙個節點都有乙個 左值 和 右值

二.規則

每乙個 後代節點 的 左值 > 父節點 的 左值

每乙個 後代節點 的 右值 

每乙個節點的 右值 > 左值

三.新增節點

新增頂級分類:

獲取該樹中 最大右值;

左值 = 最大右值 + 1;

右值 = 最大右值 + 2;

新增子節點

首先獲取 父節點右值

update `catagory` set `lft` = `lft`+2 where `lft`>`父節點右值`;

update `catagory` set `rgt` = `rgt` + 2 where `rgt`>= `父節點右值`

新增節點左值 = 父節點右值

新增節點右值 = 新增節點左值 + 1

四. 刪除節點

獲取刪除節點的左右值 $lft, $rgt

刪除該節點以及所有後代節點

delete from `catagory` where `lft`>=lft and `rgt`<=rgt"

更新左右值value=rgt-lft+1;

update `catagory` set `lft`=`lft`-value where `lft`>lft

update `catagory` set `rgt`=`rgt`-value where `rgt`>$rgt"

五.資料準備

create table `nested_category` (

`category_id` int(10) not null auto_increment comment '自增id',

`name` varchar(18) collate utf8_unicode_ci not null default '' comment '名稱',

`lft` int(4) not null,  `rgt` int(4) not null,

key `category_id` (`category_id`)

) engine=innodb auto_increment=14 default charset=utf8 collate=utf8_unicode_ci;

insert into `nested_category` values

(1,'商品',1,26),

(2,'化妝品',2,7),

(3,'食品',8,9),

(4,'酒',10,15),

(5,'服裝',16,17),

(6,'家電',18,23),

(7,'鞋帽',24,25),

(8,'面霜',3,4),

(9,'**',5,6),

(10,'白酒',11,12),

(11,'紅酒',13,14),

(12,'冰箱',19,20),

(13,'空調',21,22);

資料檢視

mysql> select * from nested_category;

| category_id | name      | lft | rgt |

|           1 | 商品    |   1 |  26 |

|           2 | 化妝品 |   2 |   7 |

|           3 | 食品    |   8 |   9 |

|           4 | 酒       |  10 |  15 |

|           5 | 服裝    |  16 |  17 |

|           6 | 家電    |  18 |  23 |

|           7 | 鞋帽    |  24 |  25 |

|           8 | 面霜    |   3 |   4 |

|           9 | **    |   5 |   6 |

|          10 | 白酒    |  11 |  12 |

|          11 | 紅酒    |  13 |  14 |

|          12 | 冰箱    |  19 |  20 |

|          13 | 空調    |  21 |  22 |

六. 獲取所有後代節點

select * from nested_category where lft > 18 and rgt 

| category_id | name   | lft | rgt |

|          12 | 冰箱 |  19 |  20 |

|          13 | 空調 |  21 |  22 |

七.計算後代數量

後代的數量 = (右值 – 左值 – 1) / 2。減少1的原因是排除該節點本身

八. 判斷葉子節點

右值 – 左值 = 1

獲取葉子節點

mysql> select * from nested_category  where rgt - lft = 1;

| category_id | name   | lft | rgt |

|           3 | 食品   |   8 |   9 |

|           5 | 服裝   |  16 |  17 |

|           7 | 鞋帽   |  24 |  25 |

|           8 | 面霜   |   3 |   4 |

|           9 | **   |   5 |   6 |

|          10 | 白酒   |  11 |  12 |

|          11 | 紅酒   |  13 |  14 |

|          12 | 冰箱   |  19 |  20 |

|          13 | 空調   |  21 |  22 |

九. 檢索單一路徑

select

parent.name,

parent.category_id,

parent.lft,

parent.rgt

from

nested_category as node, nested_category as parent

where

node.lft between parent.lft and parent.rgt and node.name = '空調'

order by parent.lft;

| name   | category_id | lft | rgt |

| 商品 |           1 |   1 |  26 |

| 家電 |           6 |  18 |  23 |

| 空調 |          13 |  21 |  22 |

3 rows in set (0.00 sec)

十. 檢索分類深度

select

node.name as name,  (count(parent.name) - 1) as deep

from

nested_category as node,

nested_category as parent

where node.lft between parent.lft and parent.rgt

group by node.name

order by node.lft

| name      | deep |

| 商品    |    0 |

| 化妝品 |    1 |

| 面霜    |    2 |

| **    |    2 |

| 食品    |    1 |

| 酒       |    1 |

| 白酒    |    2 |

| 紅酒    |    2 |

| 服裝    |    1 |

| 家電    |    1 |

| 冰箱    |    2 |

| 空調    |    2 |

| 鞋帽    |    1 |

13 rows in set (0.03 sec)

十一. 檢索某個節點的子節點(不包含後代節點)

select * from (

select

node.name as name,

(count(parent.name) - 1) as deep

from

nested_category as node,

nested_category as parent

where node.lft between parent.lft and parent.rgt

group by node.name

order by node.lft

) as a where a.deep <= 1;

| name      | deep |

| 商品    |    0 |

| 化妝品 |    1 |

| 食品    |    1 |

| 酒       |    1 |

| 服裝    |    1 |

| 家電    |    1 |

| 鞋帽    |    1 |

7 rows in set (0.00 sec)

十二.總結

我們看到上邊的獲取深度 和 檢索某個節點的子節點實現上用到了子查詢,sql語句很複雜.

所以我的解決辦法是在資料結構上增加 深度 和 父id 兩個字段

因為分類是前台頁面操作人員操作的, 也就是說操作的時候就知道深度, 每次新增時候將 深度 和 父id 帶上就可以方便的解決複雜sql語句的問題;

6 8 「最大點」 預排序

時間限制 1秒 空間限制 32768k p為給定的二維平面整數點集。定義 p 中某點x,如果x滿足 p 中任意點都不在 x 的右上方區域內 橫縱座標都大於x 則稱其為 最大的 求出所有 最大的 點的集合。所有點的橫座標和縱座標都不重複,座標軸範圍在 0,1e9 內 如下圖 實心點為滿足條件的點的集合...

FJNUOJ 1053 線段樹or前字尾預處理

時間限制 1 sec 記憶體限制 128 mb 提交 18 解決 5 提交 狀態 討論版 命題人 外部匯入 題目描述 輸入有多組輸入樣例,第一行兩個正整數n,m n m 分別表示黃主任他們的人數和第五排的座位數 n 20,m 1e6 第二行輸入m個整數,第i個數表示第i個座位的觀影值ai 1e9 a...

敗者樹多路排序

定義 敗者樹是乙個完全二叉樹,非葉子節點記錄失敗者。那麼相對於勝者樹,具有訪存小的優勢。勝者樹勝者拿走後,整條通路 從葉子到根 所有記錄的勝者資訊失效,那麼新加入節點需要從葉子一直遍歷到根,有可能每次都要寫入 更新新的勝者 而敗者樹,新加入的節點可以利用整條路徑的敗者資訊。敗者樹構建 構建過程 初始...