數據結構4.1——樹

樹(tree)

  (定義樹的一種自然的方式是遞歸的方法)一棵樹是一些節點的集合。這個集合可以是空集;若非空,則一棵樹是由稱作根(root)的節點r以及0個或多個非空的子樹T1,T2......TK組成。
  
    度(Degree):結點擁有的 子樹數稱爲結點的度。
    葉子(Leaf)或終端結點:度爲0的結點。
    非終端結點或分支結點:度不爲0的結點。
    樹的度:樹內各結點的度的最大值。
    結點的子樹的根稱爲該結點的孩子,相應的,該結點稱爲該孩子的雙親
    深度:樹中結點的最大層次稱爲樹的深度。
    如果將樹中結點的各子樹看成從左至右是有次序的,則稱該樹爲有序樹,否則稱爲無序樹
    森林:m棵互不相交的樹的集合。
   

樹的存儲結構


1.雙親表示法


以一組連續空間存儲樹的結點,同時在每個結點中,附設一個指示器指示其雙親結點在數組中的位置。

typedef struct treeNode
{
	int data;
	int parent;
}treeNode;

typedef struct tree
{
	treeNode nodes[MAX_TREE_SIZE];
	int root,n;//根的位置和結點數目;
}tree;




當要知道結點的孩子時,需要遍歷整個樹的結構,可以附設一個域來表示其第一個孩子的座標或者表示其右兄弟的位置。

2.孩子表示法


可以爲每個結點設計多個指針域,其中每個指針指向一顆子樹的根結點。
一種方法是將指針域的個數設爲樹的度(如圖)。


另一種方法,是附設一個數據表示需要的指針的個數(如圖)



還有一種更好的方法,把每個結點的孩子結點排列起來以單鏈表作爲存儲結構。則n個結點就有n個孩子鏈表,如果是葉子結點,則該鏈表爲空。



typedef struct chileNode//孩子結點
{
	int child;
	struct childNode *next;
}*childPtr;

typedef struct rootNode//表所記錄的根結點
{
	int data;
	childPtr *firstChild;
}rootNode;

typedef struct tree//樹結構
{
	rootNode nodes[MAX_TREE_SIZE];//結點數組
	int root,n;//根的位置和結點數目;
}tree;

還可以附設一個域表示其雙親的位置,這樣不僅可以知道孩子的位置,還可以知道其雙親的位置(孩子雙親表示法)。



3.孩子兄弟表示法


任意一棵樹,它的結點的第一個孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的,可以設置兩個指針,分別指向該結點的第一個孩子和此節點的右兄弟。

typedef struct treeNode
{
	int data;
	struct treeNode *firstchild,*rightsib;/* data */
}treeNode,*treePtr;


二叉樹

    每個結點至多有兩顆子樹(不存在度大於2的結點),二叉樹的子樹有左右之分,其次序不能任意顛倒。
    
    二叉樹的性質:
  • 在二叉樹的i層上至多有2^(i-1)個結點(i>=1)
  • 深度爲k的二叉樹至多有2^k-1個結點(k>=1)
  • 對任何一顆二叉樹T,如果其終端結點數爲n0,度爲2的節點數爲n2,則n0 = n2 +1

滿二叉樹

   一顆深度爲k的二叉樹有2^k-1個結點的二叉樹稱爲滿二叉樹。




完全二叉樹


    深度爲k的,有n個節點的二叉樹,當且僅當其每一個點都與深度爲k的滿二叉樹中編號從1至n的結點一一對應時,稱爲完全二叉樹。
    具有n個結點的完全二叉樹的深度爲[log2^n]+1;
    葉子結點只能出現在最下面兩層;
    最下層的葉子一定集中在左部連續位置;




二叉樹的存儲結構


     1. 順序存儲結構
         用一組地址連續的存儲單元依次自上而下、自左至右存儲完全二叉樹上的結點元素。    
     2.鏈式存儲結構
         二叉樹的結點由一個數據元素和分別指向其左、右子樹的兩個分支構成,則表示二叉樹的鏈表中的結點至少包括三個域:數據域和左右指針域。 

typedef struct BiNode
{
	chat data;
	struct BiNode *lchild,*rchild;
}BiNode,*BiTree;


遍歷二叉樹

      
     從根節點出發,按照某種次序依次訪問二叉樹中所有結點,使得每個結點被訪問一次且僅被訪問一次。
     先序遍歷 DLR 中序遍歷 LDR 後序遍歷 LRD
    
     先序遍歷二叉樹
           若樹爲空,則空操作,否則:
           訪問根節點;先序遍歷左子樹;先序遍歷右子樹。 
     中序遍歷二叉樹
           若樹爲空,則空操作,否則:
           中序遍歷左子樹;訪問根節點;中序遍歷右子樹。 
     後序遍歷二叉樹
           若樹爲空,則空操作,否則:
           後序遍歷左子樹;後序遍歷右子樹;訪問根節點; 

typedef struct BiNode
{
	chat data;
	struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
//前序遍歷二叉樹
void preOrderTraverse(BiTree T)
{
	if(NULL==T)
		return;
	printf("%c",T->data);
	preOrderTraverse(T->lchild);
	preOrderTraverse(T->rchild);
}

//前序遍歷創建二叉樹
void creatTree(BiTree *tree)//傳入指向指針的指針才能修改指針的值
{
	char c;
	scanf("%c",&c);

	if(' '==c)
	{
		*tree=NULL ;
	}
	else
	{
		*tree=(BiTree)malloc(sizeof(BiNode));
		(*tree)->data=c;
		creatTree(&(*tree)->lchild);
		creatTree(&(*tree)->rchild);		
	}
	return;
}




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