郝斌數據結構--樹

模塊二 非線性結構

定義

 

 

  1. 有且只有一個稱爲根的節點
  2. 有若干個互不相交的子樹,這些子樹本身也是一棵樹

通俗定義

  1. 樹是由節點和邊組成
  2. 但有一個節點例外,該節點沒有父節點,此節點稱爲根節點
  3. 每個節點只有一個父節點但可以有多個子節點

專業術語

  • 節點
  • 父節點
  • 子節點
  • 子孫
  • 兄弟
  • 堂兄弟
  • 深度:從根節點到最底層節點的層數稱爲深度,根節點是第一層
  • 葉子節點:沒有子節點的節點
  • 非終端節點:實際就是非葉子節點
  • 度:子節點的個數稱爲度(D的度3 樹的度指最大的度 下圖爲3)

分類

 

 

  • 一般樹:任意一個節點的子節點的個數都不受限制
  • 二叉樹: 任意一個節點的子節點的個數最多兩個,且子節點的位置不可更改(有序)
  • 森林:n個互不相交的樹的集合

二叉樹的分類

  1. 一般二叉樹
  2. 滿二叉樹 :在一棵二叉樹中,如果所有分支結點都存在左子樹和右子樹,並且所有葉子都在同一層上,這樣的二叉樹稱爲滿二叉樹。
  3. 完全二叉樹如果只是刪除了滿二叉樹最底層最右邊的連續若干個節點,這樣形成的二叉樹就是完全二叉樹

樹的存儲

二叉樹存儲

  • 連續存儲【完全二叉樹】

                優點:查找某個節點的父節點和子節(也包括判斷有沒有子節點)速度很快

                缺點:耗內存空間很大

  • 鏈式存儲

 

一般樹存儲

  • 雙親表示法     求父節點方便

 

  • 孩子表示法     求子節點方便

  • 雙親孩子表示法     求父節點和子節點都方便

  • 二叉樹表示法 孩子兄弟表示法 把一個普通樹轉化成二叉樹來存儲

        具體轉換方法:設法保證任意一個節點的左指針域指向他的第一個孩子,右指針域指向他的兄弟,只要能滿足此條件,就可以把一個普通書轉化爲二叉樹,一個普通樹轉化成的二叉樹一定沒有右子樹

森林的存儲

        先把森林轉化爲二叉樹,然後再存儲二叉樹(下圖可省略步驟1)

操作

  • 遍歷

                先序遍歷

                          先訪問根節點

                          再先序訪問左子樹

                           再線序訪問右子樹

               中序遍歷

                       中序遍歷左子樹

                       再訪問根節點

                       再中序遍歷右子樹

                後序遍歷

                       後序遍歷左子樹

                      後序遍歷右子樹

                      再訪問根節點

                      左到右先葉子後結點的方式遍歷訪問左右子樹,最後是訪問根結點

  • 已知兩種遍歷順序求原始二叉樹

通過先序和中序 或者 中序和後序可以還原出原始的二叉樹,但是通過先序和後序是無法還原出二叉樹的

                       實例一

           實例二

            實例三

樹的應用

  • 樹是數據庫中數據組織一種重要形式
  • 操作系統子父進程的關係本身就是一顆樹
  • 面嚮對象語言中類的繼承關係
  • 赫夫曼樹

程序演示

# include <stdio.h>
# include <malloc.h>
struct BTNode 
{
	char data;
	struct BTNode *pLchild; // p是指針 L是左 child是孩子
	struct BTNode *pRchild;
};

struct BTNode * CreateBTree();
void PreTraverseBTree(struct BTNode *pT);
void InTraverseBTree(struct BTNode *pT);
void PostTraverseBTree(struct BTNode *pT);

int main(void)
{
	struct BTNode *pT = CreateBTree();
	//PreTraverseBTree(pT);
	//InTraverseBTree(pT);
	PostTraverseBTree(pT);
	return 0;
}

struct BTNode * CreateBTree(void)
{
	struct BTNode *pA = (struct BTNode *)malloc(sizeof(struct BTNode));
	struct BTNode *pB = (struct BTNode *)malloc(sizeof(struct BTNode));
	struct BTNode *pC = (struct BTNode *)malloc(sizeof(struct BTNode));
	struct BTNode *pD = (struct BTNode *)malloc(sizeof(struct BTNode));
	struct BTNode *pE = (struct BTNode *)malloc(sizeof(struct BTNode));
	
	pA->data = 'A';
	pB->data = 'B';
	pC->data = 'C';
	pD->data = 'D';
	pE->data = 'E';

	pA->pLchild = pB;
	pA->pRchild = pC;
	pB->pLchild = pB->pRchild = NULL;
	pC->pLchild = pD;
	pC->pRchild = NULL;
	pD->pLchild = NULL;
	pD->pRchild = pE;
	pE->pLchild = pE->pRchild = NULL;
	return pA;
}

void PreTraverseBTree(struct BTNode *pT)
{
	/*先訪問根節點
	再先序訪問左子樹
	再先序訪問右子樹*/
	if (NULL != pT)
	{
		printf("%c ", pT->data);
		if (NULL != pT->pLchild)
		{
			PreTraverseBTree(pT->pLchild);
		}
		if (NULL != pT->pRchild)
		{
			PreTraverseBTree(pT->pRchild);
		}
	}
}

void InTraverseBTree(struct BTNode *pT)
{
	if (NULL != pT)
	{
		
		if (NULL != pT->pLchild)
		{
			InTraverseBTree(pT->pLchild);
		}
		printf("%c ", pT->data);
		if (NULL != pT->pRchild)
		{
			InTraverseBTree(pT->pRchild);
		}
	}
}

void PostTraverseBTree(struct BTNode *pT)
{
	if (NULL != pT)
	{
		if (NULL != pT->pLchild)
		{
			PostTraverseBTree(pT->pLchild);
		}
		if (NULL != pT->pRchild)
		{
			PostTraverseBTree(pT->pRchild);
		}
		printf("%c ", pT->data);
	}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章