1. 程式人生 > >樹形遞迴遍歷實現多級評論

樹形遞迴遍歷實現多級評論

最近參加了學校的網頁設計大賽,做了一個論壇網站,期間後臺的多級評論用了我很多時間,什麼是多級評論呢,也就是針對某一條評論,其他使用者都可以在該評論基礎上回復對方,這樣也就形成了一條樹形結構,我用了遞迴來實現樹的遍歷,感覺這個演算法很有用,在許多方面都有可能用到,比如說像QQListView分組顯示都可以用它來實現。

具體實現思路:

1、通過構建節點來記錄資料,節點要求:記錄父節點;記錄自身節點,記錄子節點,記錄節點所在樹。

2、將已經記錄了資訊的節點儲存到集合表中,對集合表進行遍歷排序。

3、將排好序的集合表用於專案中遍歷顯示。

接下來給大家展示核心程式碼:

我還是來一張網站多級評論圖片(嘿嘿):

這裡寫圖片描述
一、Node類:

public class Node 
{
    private int id;//自己的id,-1時表示葉子節點
    private int p_id;//父節點id,0時表示根節點
    private int root_number;//這個是每條樹的唯一標識,表示該節點所在根
    private Node parent;//記錄父節點,每個節點只有一個父節點
    private List<Node> children;//記錄子節點,子節點可以有多個
    //其他屬性根據具體需求新增,以上都是必須的

    public Node(int id, int
p_id, int root_number) { this.id = id; this.p_id = p_id; this.root_number = root_number; } public int getId() { return this.id; } public int getPId() { return this.p_id; } public int getRootNumber() { return this
.root_number; } public void setParent(Node parent) {//設定父節點 this.parent = parent; } public Node getParent() {//獲取該節點的父節點 return this.parent; } public void setChildren(Node child) {//記錄子節點 this.children.Add(child); } public boolisRoot() {//判斷是否為根 return this.p_id == 0; } public bool isLeaf() {//判斷是否為葉子節點 return this.id == -1; } public List<Node> getChidrenList() {//獲取該節點的的所有子節點集合表 return this.children; } }

二、NodesHelper類:節點進行遍歷排序

 public class NodesHelper
    {
        public static List<Node> getConvertNode(List<Node> list) {//對外開放介面,返回排序後的集合表
        //各節點之間建立連線關係
            connectNodes(list);
            //獲取所有的根節點
            List<Node> rootNodes = getRootNodes(list);
            //建立空表,儲存排序後的節點
            List<Node> result = new List<Node>();


            for (int i = 0; i < rootNodes.Count; i++)
            {//根據每個根節點,將其所屬節點新增到空表中
                //遞迴新增節點
                addNodeToResult(result, rootNodes[i]);
            }

            return result;
        }



        private static void connectNodes(List<Node> list)
        {//各節點之間建立連線關係
            for (int i = 0; i < list.Count -1; i++)
            {
                Node nodeLast = list[i];
                for (int j = i + 1; j < list.Count; j++)
                {
                    Node nodeNext = list[j];
                    if (nodeLast.getRootNumber() == nodeNext.getRootNumber())//判斷是否處於同一樹
                    {
                        if (nodeNext.getPId() == nodeLast.getId())
                        {
                            nodeLast.setChildren(nodeNext);
                            nodeNext.setParent(nodeLast);
                        }
                        else if (nodeNext.getId() == nodeLast.getPId())
                        {
                            nodeNext.setChildren(nodeLast);
                            nodeLast.setParent(nodeNext);
                        }
                    }
                }
            }

        }

        private static List<Node> getRootNodes(List<Node> list)
        {//獲取所有的根節點
            List<Node> rootNodes = new List<Node>();

            int length = list.Count;
            for (int i = 0; i < length; i++)
            {
                    if (list[i].isRoot())
                    {
                        rootNodes.Add(list[i]);
                    }
            }
                return rootNodes;
        }

        private static void addNodeToResult(List<Node> result, Node node)//遞迴新增節點
        {
            result.Add(node);

            if (node.isLeaf())
            {
                return;
            }

            List<Node> list = node.getChildrenList();

            for (int i = 0; i < list.Count; i++)
            {
                addNodeToResult(result, list[i]);
            }
        }
    }

好了,程式碼就這些了。我用的是C#寫的,其他語言實現也是這樣的思路,希望對你有幫助。