【java基礎 4】樹形結構數據呈現的非遞歸算法(循環)實現

1、基本概況

上一篇博客介紹到用遞歸實現樹結構數據的查找,那麼這篇博客,我就結合本身對於樹的理解,而後用一種非遞歸的方式進行樹結構數據的處理。首先,改造數據庫表設計,加入度的概念:javascript



首先,layer的設計,是來源於Word文檔的目錄帶來的靈感。想想我本身在寫Word文檔的時候,經過標題1,標題2等的設立,而後就可能自動生成目錄。我感受這個和我要完成的樹結構數據的處理有共同之處。固然,在這裏的010000,是我本身對於樹的度的表示,主要是用於排序,然後面的depth,則是對於我本身方便在Java控制檯打印額外添加的一個字段(實際應用,不須要)css


而後是實體類設計:java

<span style="font-family:KaiTi_GB2312;font-size:18px;">	private String id;
	private String name;
	private String pid;
	private String layer;
	private String depth;</span>

創建實體類的get和set方法


2、代碼實現

1,查詢全部的數據

<span style="font-family:KaiTi_GB2312;font-size:18px;">	public List<TreeEntity> findAllData() {
		<span style="color:#ff0000;">String sql = "select * from test where id is not null order by layer ASC";
</span>
		List<TreeEntity> treeList = null;

		try {
			conn = DbUtil.getConnection();
			pstmt = conn.prepareStatement(sql);
			rs = pstmt.executeQuery();

			treeList = new ArrayList<TreeEntity>();
			
			while (rs.next()) {
				TreeEntity myTree = new TreeEntity();
				myTree.setId(rs.getString("id"));
				myTree.setName(rs.getString("name"));
				myTree.setPid(rs.getString("pid"));
				myTree.setDepth(rs.getString("depth"));
				treeList.add(myTree);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DbUtil.close(pstmt);
			DbUtil.close(conn);
		}
		return treeList;
	}</span>

事實上,執行了這個方法以後,數據庫的數據,就已是按照菜單形式排列整齊的數據了。那麼,怎麼顯示的更爲美觀呢?

2,顯示樹

<span style="font-family:KaiTi_GB2312;font-size:18px;">public void displayTree(){
		List<TreeEntity> List=this.findAllData();
		String prefix="";
		for(int i=0; i<List.size(); i++){
			if("1".equals(List.get(i).getDepth())){
				prefix="|-";
			}
			if("2".equals(List.get(i).getDepth())){
				prefix="|----";
			}
			if("3".equals(List.get(i).getDepth())){
				prefix="|--------";
			}
			System.out.println(prefix+List.get(i).getName());
		}
	}</span>

首先,這裏有幾個if語句,是我藉助depth字段的值,來進行數據打印的一個過程。通常來講,做爲一個系統的左側邊菜單,度的最大值,應該是在5個左右,少的話,直接在這裏寫。多的話,則有工廠方法模式能夠簡單改造。(並且,這一點只是我要在控制檯打印出一棵樹,本身額外加上的)node

在實際應用中,好比說JQuery的ZTree插件,則有專門對應的簡單Array形式的數據加載,以下:
sql

第一種格式加載:標準的帶有父子關係的ZTree加載數據庫

var zTreeNodes = [   
    {"id":1, "name":"test1", "nodes":[   
      {"id":11, "name":"test11", "nodes":[   
        {"id":111, "name":"test111"}   
      ]},   
      {"id":12, "name":"test12"}   
    ]},   
    ......   
];  

第二種格式加載:帶有父子關係的簡單Array格式加載

var treeNodes = [                                                                         
    {"id":1, "pId":0, "name":"test1"},   
    {"id":11, "pId":1, "name":"test11"},   
    {"id":12, "pId":1, "name":"test12"},   
    {"id":111, "pId":11, "name":"test111"},   
    ......   
];  

在實際應用的時候,徹底能夠採用第二種數據加載方式,讓程序變得更爲簡單!


3,主程序代碼及結果

<span style="font-family:KaiTi_GB2312;font-size:18px;">	public static void main(String[] args) {
		TreeDepth tree = new TreeDepth();
		tree.displayTree();
	}</span>




3、代碼思考

能夠看出的是,改造數據庫設計以後,只用了1次循環,就實現了最終的效果,而沒有用遞歸。那麼問題的關鍵點有:每次插入數據的時候,layer的值填充問題,那麼這個實際上是有規律的,每一個人均可能會有一套本身的填充規律,就好比說個人靈感則來自於Word文檔的目錄實現。markdown

在用非遞歸實現了這個樹的打印以後,我忽然就明白了以前有一個姑娘問個人問題:她說爲何每次左側邊的菜單欄加載的時候,都要從上往下加載,而不是一次性加載完。今天跟了每一步代碼以後發現,由於使用遞歸的時候,就是先把每個結點的孩子結點所有遍歷結束後,纔會開始加載下一個結點。而使用非遞歸則不同,由於它是一次性直接加載完全部的數據,因此是一次性加載完畢。數據庫設計

4、總結

對於平時的學習,仍是多總結總結吧。我感受,遞歸不遞歸的,其實也不那麼重要,根據本身的實際狀況進行取捨。函數

循環方法比遞歸方法快, 由於循環避免了一系列函數調用和返回中所涉及到的參數傳遞和返回值的額外開銷。

學習

遞歸和循環之間的選擇。通常狀況下, 當循環方法比較容易找到時, 你應該避免使用遞歸。

相關文章
相關標籤/搜索