【Tree 1】樹形結構數據呈現的遞歸算法實現


一、基本概況

在我的項目中,常常會用到樹形結構的數據,最為明顯的就是左邊菜單欄,類似於window folder一樣的東西。


而我之前一直是借助前端封裝好的ZTree等工具實現展示,而后台則通常使用遞歸進行數據的查找。通常,我們在設計數據庫表的時候,一般會使用三個字段:id,name,pid。如下圖所示:



二、代碼實現

首先是建立實體類:

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


編寫實體類的get和set方法。


然后,我們通常會有以下的幾個方法(通常情況,封裝粒度不同,方法的實現個數和內容也不同):

1,找到所有的父節點

<span style="font-family:KaiTi_GB2312;font-size:18px;">public List<TreeEntity> findAllParents() {
		String sql = "select * from test where pid is null or pid='' ";

		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"));
				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 List<TreeEntity> findChildByPid(String pid) {
		String sql = "select * from test where pid='" + pid + "'";

		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"));
				treeList.add(myTree);
			}

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


備注:這兩個方法可以合並,這里是為了讓自己更好的理解,而寫了兩個方法。可以判斷傳入的pid的值,確定其查找的是父節點,還是根據父節點查找子節點。


3,查看是否存在子節點

<span style="font-family:KaiTi_GB2312;font-size:18px;">	public boolean HasChild(String pid) {
		boolean flag = false;
		String sql = "select * from test where pid='" + pid + "'";
		int count = 0;
		try {
			conn = DbUtil.getConnection();
			pstmt = conn.prepareStatement(sql);
			rs = pstmt.executeQuery();

			while(rs.next()){
				count++;
			}

			if (count > 0) {
				flag = true;
			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DbUtil.close(pstmt);
			DbUtil.close(conn);
		}

		return flag;
	}</span>


4,使用遞歸拼接父節點的子節點

 

<span style="font-family:KaiTi_GB2312;font-size:18px;">	public void BindChildByParent(String pid, String prefix) {
		if (this.HasChild(pid)) {
			// 得到當前父節點下的所有孩子
			List<TreeEntity> list = this.findChildByPid(pid);
			// 循環打印當前父節點下的孩子
			for (int i = 0; i < list.size(); i++) {
				System.out.println("|----"+prefix+list.get(i).getName());
				if (this.HasChild(list.get(i).getId())) {
					this.BindChildByParent(list.get(i).getId(),"--");
				}
			}
		}
	}</span>

5,打印樹

 

<span style="font-family:KaiTi_GB2312;font-size:18px;">	public void TreeHtml() {

		// 找到所有的父節點
		List<TreeEntity> treeList1 = this.findAllParents();

		if (treeList1 != null) {
			for (int i = 0; i < treeList1.size(); i++) {
				TreeEntity tree = treeList1.get(i);
				// 打印父節點
				System.out.println("|--" + tree.getName());
				// 綁定孩子
				this.BindChildByParent(tree.getId(), "");
			}
		} else {
			System.out.println("沒有數據!");
		}

	}</span>



6,main方法調用,及實現結果

 

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




三、代碼思考

 

最近,由於考試,看了數據結構 這本書。首先,我是在想,大家都用的這種方法,到底好在哪兒了,還有就是,為什么在我們的數據庫設計中,樹的度的概念沒有體現出來。其次是,對於樹的遍歷,有非遞歸的方式,我想也許,我也可以不用遞歸,就實現樹形結構的數據查找。於是乎,請看下文:


為什么我不想用遞歸:

1,經過查證,系統使用遞歸算法,需要系統堆棧處理。當樹的深度很大時,由於系統支撐不住,會呈現死亡狀態。

2,遞歸算法的運行效率較低,無論是耗費的計算時間還是占用的存儲空間都比非遞歸算法要多。

3,最為直接的原因:很長一段時間里,我都不能理解遞歸算法,我總在想,可不可以用我會的,我喜歡的 方式,去解決我面臨的問題?


遞歸的好處:

結構清晰,可讀性強,而且容易用數學歸納法來證明算法的正確性,因此它為設計算法、調試程序帶來很大方便。 

五、總結

事實證明,對於樹結構的數據搜索,完全可以不使用遞歸。我總算完成了我自己的夢想,終於,我可以不用遞歸,也可以實現樹結構的查找了。更為高興的是,事實證明,采用非遞歸的方式,在我接觸到的項目中,它有更大的優勢。

下一篇播客,介紹怎么用非遞歸的方式查找樹結構的數據!至此,我好像覺得自己又變得不一樣了的感覺,我把數據結構這本書的內容,完全結合到自己的項目中,並且用這些東西,去改造去理解我的代碼。開心,不過還有圖,我不知道怎么用的,關於圖,我想到了非關系型數據庫,再去驗證吧!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM