1. 程式人生 > 實用技巧 >選單樹形展示的遞迴與非遞迴形式實現

選單樹形展示的遞迴與非遞迴形式實現

1.遞迴形式實現

節點分為三種:根節點、中間節點、葉子節點,其中一個樹可以有多個根節點
結構體


type MenuTree struct {
	Name 			string                  `json:"name"`
	ID   			string                  `json:"id"`     
	Description             string                  `json:"description"`
	ParentID   		string                  `json:"parentId"`
	HeaderGroupID           string                  `json:"headerGroupId"`//用於記錄該節點所屬的根節點,可以便於查詢指定根節點的所有child
	Children               []*MenuTree 		`json:"childrens"`
}

獲取指定節點的葉子節點

func GetNodeLeafIds(menuTree *MenuTree, nodeID string) []string {
	node := findNode(menuTree, nodeID)
	if node == nil {
		return nil
	}
	ids := make([]string, 0)
	getLeafIds(node, &ids)
	return ids
}

查詢某一中間節點是否有包含指定節點

func findNode(menuTree *MenuTree, nodeID string) *MenuTree {
	if menuTree.ID == nodeID {
		return menuTree
	}
	for _, child := range menuTree.Children {
		if child.ID == nodeID {
			return child
		}
		findNode(child, nodeID)
	}
	return nil
}

獲取指定節點的所有葉子節點

func getLeafIds(node *MenuTree, lefts *[]string) {
	for _, child := range node.Children {
		if child.Children == nil || len(child.Children) == 0 {
			*lefts = append(*lefts, child.ID)
		}
		getLeafIds(child, lefts)
	}
}

獲取所有根節點

func getRoots(datas []*MenuTree) []*MenuTree {
	roots := []*MenuTree{}
	for _, data := range datas {
		if data.ParentID == "" {//父節點為空的為根節點
			root := MenuTree{
			        Name         :		data.Name,              
				ID           :   	data.ID,	                  
				Description  :    	data.Description,                 
				ParentID     :   	data.ParentID,	                  
				HeaderGroupID:  	data.HeaderGroupID,               
				Children     :      []*MenuTree{},
			}
			roots = append(roots, &root)
		}
	}
	return roots
}

給指定的根節點構建樹,datas為所有選單的資料,root為指定根節點

func buildChild(datas []*MenuTree, root *MenuTree) *MenuTree {
	for _, data := range datas {
		if data.ParentGroupID == node.DeviceGroupID {
			node.Children = append(node.Children, buildChild(datas, data))
		}
	}
	return node
}

構建所有根節點的樹

func BuildTree(allMenus []*MenuTree) []*MenuTree {
	roots := getRoots(allMenus)
	for _, root := range roots {
		buildChild(allMenus, root)
	}
	return roots
}

2.非遞迴形式實現

func buildMenuTree(allMenus []*MenuTree ) map[string]*MenuTree {

	temp := map[string]*MenuTree{}

	result := map[string]*MenuTree{}
	for _, menu := range allMenus {
		temp[menu.ID] = &menu
	}

	for _, node := range temp {
		if temp[node.ParentID] == nil {
			result[node.ID] = node
		} else {
			temp[node.ParentID].Children = append(temp[node.ParentID].Children, node)
		}
	}

	return result
}

如果覺得寫得不好,歡迎指出;如果覺得寫得不錯,歡迎大佬讚賞。