一.概念
左右值無限級分類,也稱為預排序樹無限級分類
是一種有序的樹狀結構
於這些樹狀結構中的每乙個節點都有乙個 左值 和 右值
二.規則
每乙個 後代節點 的 左值 > 父節點 的 左值
每乙個 後代節點 的 右值
每乙個節點的 右值 > 左值
三.新增節點
新增頂級分類:
獲取該樹中 最大右值;
左值 = 最大右值 + 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...
敗者樹多路排序
定義 敗者樹是乙個完全二叉樹,非葉子節點記錄失敗者。那麼相對於勝者樹,具有訪存小的優勢。勝者樹勝者拿走後,整條通路 從葉子到根 所有記錄的勝者資訊失效,那麼新加入節點需要從葉子一直遍歷到根,有可能每次都要寫入 更新新的勝者 而敗者樹,新加入的節點可以利用整條路徑的敗者資訊。敗者樹構建 構建過程 初始...