1. 程式人生 > 其它 >Java多叉樹遞迴演算法構造樹形結構JSON

Java多叉樹遞迴演算法構造樹形結構JSON

構造如下JSON結構:

{
  id: '100000',
  text: '廊坊銀行總行',
  children: [
    {
      id: '110000',
      text: '廊坊分行',
      children: [
        {
          id: '113000',
          text: '廊坊銀行開發區支行',
          leaf: true
        },
        {
          id: '112000',
          text: '廊坊銀行解放道支行',
          children: [
            {
              id: '112200',
              text: '廊坊銀行三大街支行',
              leaf: true
            },
            {
              id: '112100',
              text: '廊坊銀行廣陽道支行',
              leaf: true
            }
          ]
        },
        {
          id: '111000',
          text: '廊坊銀行金光道支行',
          leaf: true
        }
      ]
    }
  ]
}

  

實現這樣一顆樹,需要設計兩個類:樹類(MultiwayTree)、節點類(Node);排序時還需要一個比較器類(NodeIDComparator);為了方便演示,還需要構造一些假的層次資料,因此還需要建一個構造假資料的類(VirtualDataGenerator),以下程式碼拷貝出來之後可直接執行測試:

package test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Collections;

/**
 * 多叉樹類
 */
public class MultiwayTree {
	public static void main(String[] args) {
		// 讀取層次資料結果集列表 
		List dataList = VirtualDataGenerator.getVirtualResult();

		// 節點對映表,用於臨時儲存節點物件
		HashMap nodeMap = new HashMap();
		// 根節點
		Node root = null;
		// 將結果集存入對映表(後面將藉助對映表構造多叉樹)
		for (Iterator it = dataList.iterator(); it.hasNext();) {
			Map dataRecord = (Map) it.next();
			Node node = new Node();
			node.id = (String) dataRecord.get("id");
			node.text = (String) dataRecord.get("text");
			node.parentId = (String) dataRecord.get("parentId");
			nodeMap.put(node.id, node);
		}
		// 構造無序的多叉樹
		Set entrySet = nodeMap.entrySet();
		for (Iterator it = entrySet.iterator(); it.hasNext();) {
			Node node = (Node) ((Map.Entry) it.next()).getValue();
			if (node.parentId == null || node.parentId.equals("")) {
				root = node;
			} else {
				((Node) nodeMap.get(node.parentId)).addChild(node);
			}
		}
		// 輸出無序的樹形結構的JSON字串
		System.out.println(root);
		// 對多叉樹進行橫向排序
		root.sortChildren();
		// 輸出有序的樹形結構的JSON字串
		System.out.println(root);

		// 程式輸出結果如下:
		//
		// 無序的樹形結構(格式化後的結果,可使用JSON格式化工具檢視,例如  http://jsonviewer.stack.hu/ 線上檢視器):  
		//  {
		//   id : '100000', 
		//   text : '廊坊銀行總行', 
		//   children : [
		//     {
		//     id : '110000', 
		//     text : '廊坊分行', 
		//     children : [
		//       {
		//       id : '113000', 
		//       text : '廊坊銀行開發區支行', 
		//       leaf : true
		//       },
		//       {
		//       id : '111000', 
		//       text : '廊坊銀行金光道支行', 
		//       leaf : true
		//       },
		//       {
		//       id : '112000', 
		//       text : '廊坊銀行解放道支行', 
		//       children : [
		//         {
		//         id : '112200', 
		//         text : '廊坊銀行三大街支行', 
		//         leaf : true
		//         },
		//         {
		//         id : '112100', 
		//         text : '廊坊銀行廣陽道支行', 
		//         leaf : true
		//         }
		//       ]
		//       }
		//     ]
		//     }
		//   ]
		//  }

		// 有序的樹形結構(格式化後的結果):
		//  {
		//   id : '100000', 
		//   text : '廊坊銀行總行', 
		//   children : [
		//     {
		//     id : '110000', 
		//     text : '廊坊分行', 
		//     children : [
		//       {
		//       id : '111000', 
		//       text : '廊坊銀行金光道支行', 
		//       leaf : true
		//       },
		//       {
		//       id : '112000', 
		//       text : '廊坊銀行解放道支行', 
		//       children : [
		//         {
		//         id : '112100', 
		//         text : '廊坊銀行廣陽道支行', 
		//         leaf : true
		//         },
		//         {
		//         id : '112200', 
		//         text : '廊坊銀行三大街支行', 
		//         leaf : true
		//         }
		//       ]
		//       },
		//       {
		//       id : '113000', 
		//       text : '廊坊銀行開發區支行', 
		//       leaf : true
		//       }
		//     ]
		//     }
		//   ]
		//  }  

	}

}

/**
 * 節點類
 */
class Node {
	/**
	 * 節點編號
	 */
	public String id;

	/**
	 * 節點內容
	 */
	public String text;

	/**
	 * 父節點編號
	 */
	public String parentId;

	/**
	 * 孩子節點列表
	 */
	private List children = new ArrayList();

	// 新增孩子節點
	public void addChild(Node node) {
		children.add(node);
	}

	// 先序遍歷,拼接JSON字串
	public String toString() {
		String result = "{" + "id : '" + id + "'" + ", text : '" + text + "'";
		if (children.size() != 0) {
			result += ", children : [";
			for (int i = 0; i < children.size(); i++) {
				result += ((Node) children.get(i)).toString() + ",";			
			}
			result = result.substring(0, result.length() - 1);
			result += "]";
		} else {
			result += ", leaf : true";
		}
		return result + "}";
	}

	// 兄弟節點橫向排序
	public void sortChildren() {
		if (children.size() != 0) {
			// 對本層節點進行排序(可根據不同的排序屬性,傳入不同的比較器,這裡 傳入ID比較器)
			Collections.sort(children, new NodeIDComparator());
			// 對每個節點的下一層節點進行排序			
			for (int i = 0; i < children.size(); i++) {
				((Node) children.get(i)).sortChildren();
			}
		}
	}

}

/**
 * 節點比較器
 */
class NodeIDComparator implements Comparator {
	// 按照節點編號比較
	public int compare(Object o1, Object o2) {
		int j1 = Integer.parseInt(((Node) o1).id);
		int j2 = Integer.parseInt(((Node) o2).id);
		return (j1 < j2 ? -1 : (j1 == j2 ? 0 : 1));
	}
}

/**
 * 構造虛擬的層次資料
 */
class VirtualDataGenerator {
	// 構造無序的結果集列表,實際應用中,該資料應該從資料庫中查詢獲得;
	public static List getVirtualResult() {
		List dataList = new ArrayList();

		HashMap dataRecord1 = new HashMap();
		dataRecord1.put("id", "112000");
		dataRecord1.put("text", "廊坊銀行解放道支行");
		dataRecord1.put("parentId", "110000");

		HashMap dataRecord2 = new HashMap();
		dataRecord2.put("id", "112200");
		dataRecord2.put("text", "廊坊銀行三大街支行");
		dataRecord2.put("parentId", "112000");

		HashMap dataRecord3 = new HashMap();
		dataRecord3.put("id", "112100");
		dataRecord3.put("text", "廊坊銀行廣陽道支行");
		dataRecord3.put("parentId", "112000");

		HashMap dataRecord4 = new HashMap();
		dataRecord4.put("id", "113000");
		dataRecord4.put("text", "廊坊銀行開發區支行");
		dataRecord4.put("parentId", "110000");

		HashMap dataRecord5 = new HashMap();
		dataRecord5.put("id", "100000");
		dataRecord5.put("text", "廊坊銀行總行");
		dataRecord5.put("parentId", "");

		HashMap dataRecord6 = new HashMap();
		dataRecord6.put("id", "110000");
		dataRecord6.put("text", "廊坊分行");
		dataRecord6.put("parentId", "100000");

		HashMap dataRecord7 = new HashMap();
		dataRecord7.put("id", "111000");
		dataRecord7.put("text", "廊坊銀行金光道支行");
		dataRecord7.put("parentId", "110000");

		dataList.add(dataRecord1);
		dataList.add(dataRecord2);
		dataList.add(dataRecord3);
		dataList.add(dataRecord4);
		dataList.add(dataRecord5);
		dataList.add(dataRecord6);
		dataList.add(dataRecord7);

		return dataList;
	}
}