二叉樹的實現與操作(C語言實現)

     

     二叉樹的定義:

    上一篇的樹的通用表示法太過於複雜,由此這裏採用了孩子兄弟表示法來構建二叉樹。

孩子兄弟表示法:

   每個結點包含一個數據指針和兩個結點指針

--->數據指針:指向保存於樹中的數據

--->孩子結點指針:指向第一個孩子

--->兄弟結點指針:指向第一個右兄弟


二叉樹是由 n( n>=0 ) 個結點組成的有限集,該集合或者爲空,或者是由一個根結點加上兩棵分別稱爲左子樹和右子樹的、互不相交的二叉樹組成。


特殊的二叉樹:

定義1:滿二叉樹(Full Binary Tree)

如果二叉樹中所有分支結點的度數都爲2,且葉子結點都在同一層次上,則稱做這類二叉樹爲滿二叉樹


定義2:完全二叉樹

如果一顆具有N個結點的高度爲K的二叉樹,它的每一個結點都與高度爲K的滿二叉樹中的編號爲1---N的結點一一對應,則稱這課二叉樹爲完全二叉樹(從上到下從左到右編號)。

注:完全二叉樹的葉結點僅僅出現在最下面二層,

      最下面的葉結點一定出現在左邊;

      倒數第二層的葉結點一定出現在右邊

  完全二叉樹中度爲1的結點只有左孩子

  同樣結點數的二叉樹,完全二叉樹的高度最小



二叉樹的深層性質

 

性質1

 在二叉樹的第i層最多有2i-1個結點。(i>=1

性質2

 深度爲K的二叉樹最多有2k-1個結點(k>=0

性質3

 對任何一顆二叉樹,如果其葉結點有n0個,度爲2的結點的非葉結點有n2個,則有n0=n2+1

性質4

 具有n個結點的完全二叉樹的高度爲[log2n]+1

 

性質5

  一顆有n個結點的二叉樹(高度爲[log2n]+1),按層次對結點進行編號(從上到下,從左到右),對任意結點i有:

   如果i=1,則結點i是二叉樹的根,

   如果i>1,則其雙親結點爲[i/2]

   如果2i<=n,則結點i的左孩子爲2i

   如果2i>n,則結點i無左孩子,

   如果2i+1<=n,則結點i的右孩子爲2i+1,

   如果2i+1>n,則結點i無右孩子



以下是代碼:


頭文件:

#ifndef _BTREE_H_
#define _BTREE_H_

#define BT_LEFT 0
#define BT_RIGHT 1

typedef void BTree;     //樹
typedef unsigned long long BTPos;  //要插入結點的位置,是一個十六進制數字

typedef struct _tag_BTreeNode BTreeNode;   //定義樹結點
struct _tag_BTreeNode
{
	BTreeNode* left;
	BTreeNode* right;
};

typedef void (BTree_Printf)(BTreeNode*);

BTree* BTree_Create();

void BTree_Destroy(BTree* tree);

void BTree_Clear(BTree* tree);

int BTree_Insert(BTree* tree, BTreeNode* node, BTPos pos, int count, int flag);

BTreeNode* BTree_Delete(BTree* tree, BTPos pos, int count);

BTreeNode* BTree_Get(BTree* tree, BTPos pos, int count);

BTreeNode* BTree_Root(BTree* tree);

int BTree_Height(BTree* tree);

int BTree_Count(BTree* tree);

int BTree_Degree(BTree* tree);

void BTree_Display(BTree* tree, BTree_Printf* pFunc, int gap, char div);

#endif

源文件:

#include "stdafx.h"
#include <stdio.h>
#include <malloc.h>
#include "BTree.h"

typedef struct _tag_BTree TBTree;
struct _tag_BTree    //樹的頭結點定義
{
	int count;
	BTreeNode* root;
};

//打印函數
static void recursive_display(BTreeNode* node, BTree_Printf* pFunc, int format, int gap, char div) 
{
	int i = 0;

	if( (node != NULL) && (pFunc != NULL) )
	{
		//先打印格式符號
		for(i=0; i<format; i++)
		{
			printf("%c", div);
		}

		//打印樹中具體的數據
		pFunc(node);

		printf("\n");

		//如果左 或者 右結點不爲空纔打印
		if( (node->left != NULL) || (node->right != NULL) )
		{
			recursive_display(node->left, pFunc, format + gap, gap, div);
			recursive_display(node->right, pFunc, format + gap, gap, div);
		}
	}
	//如果結點爲空 就打印 格式符號
	else
	{
		for(i=0; i<format; i++)
		{
			printf("%c", div);
		}
		printf("\n");
	}
}

//統計樹中結點的數量
static int recursive_count(BTreeNode* root) 
{
	int ret = 0;

	if( root != NULL )
	{
		ret = recursive_count(root->left) + 1 + recursive_count(root->right);
	}

	return ret;
}

//計算樹的高度
static int recursive_height(BTreeNode* root) 
{
	int ret = 0;

	if( root != NULL )
	{
		int lh = recursive_height(root->left);
		int rh = recursive_height(root->right);

		ret = ((lh > rh) ? lh : rh) + 1;
	}

	return ret;
}

//計算樹的度
static int recursive_degree(BTreeNode* root) 
{
	int ret = 0;

	if( root != NULL )
	{
		if( root->left != NULL )
		{
			ret++;
		}

		if( root->right != NULL )
		{
			ret++;
		}

		if( ret == 1 )
		{
			int ld = recursive_degree(root->left);
			int rd = recursive_degree(root->right);

			if( ret < ld )
			{
				ret = ld;
			}

			if( ret < rd )
			{
				ret = rd;
			}
		}
	}

	return ret;
}

BTree* BTree_Create() 
{
	TBTree* ret = (TBTree*)malloc(sizeof(TBTree));

	if( ret != NULL )
	{
		ret->count = 0;
		ret->root = NULL;
	}

	return ret;
}

void BTree_Destroy(BTree* tree)
{
	free(tree);
}

void BTree_Clear(BTree* tree) 
{
	TBTree* btree = (TBTree*)tree;

	if( btree != NULL )
	{
		btree->count = 0;
		btree->root = NULL;
	}
}

//tree  目標樹  node 要插入結點   pos 要插入位置  count 移動步數  flag  插入位置是左還是右
int BTree_Insert(BTree* tree, BTreeNode* node, BTPos pos, int count, int flag) 
{
	TBTree* btree = (TBTree*)tree;
	int ret = (btree != NULL) && (node != NULL) && ((flag == BT_LEFT) || (flag == BT_RIGHT));
	int bit = 0;

	if( ret )
	{
		BTreeNode* parent = NULL;
		BTreeNode* current = btree->root;

		node->left = NULL;
		node->right = NULL;

		while( (count > 0) && (current != NULL) )
		{
			//位置最低位與1進行按位與運算,得知是往左走還是往右走
			bit = pos & 1;
			//表示位置的十六進制向右移動一位
			pos = pos >> 1;

			//parent用來掛要插入的結點
			parent = current;

			if( bit == BT_LEFT )
			{
				current = current->left;
			}
			else if( bit == BT_RIGHT )
			{
				current = current->right;
			}

			count--;
		}

		//插入的結點掛上中間被砍斷的剩下的結點
		if( flag == BT_LEFT )
		{
			node->left = current;
		}
		else if( flag == BT_RIGHT )
		{
			node->right = current;
		}

		//將要插入的結點掛上
		if( parent != NULL )
		{
			if( bit == BT_LEFT )
			{
				parent->left = node;
			}
			else if( bit == BT_RIGHT )
			{
				parent->right = node;
			}
		}
		else
		{
			btree->root = node;
		}

		btree->count++;
	}

	return ret;
}


//刪除與插入基本類似,只不過將要刪除的結點的父結點的left或者right指針以及所有的子節點置爲NULL而已
BTreeNode* BTree_Delete(BTree* tree, BTPos pos, int count) 
{
	TBTree* btree = (TBTree*)tree;
	BTreeNode* ret = NULL; 
	int bit = 0;

	if( btree != NULL )
	{
		BTreeNode* parent = NULL;
		BTreeNode* current = btree->root;

		while( (count > 0) && (current != NULL) )
		{
			bit = pos & 1;
			pos = pos >> 1;

			parent = current;

			if( bit == BT_LEFT )
			{
				current = current->left;
			}
			else if( bit == BT_RIGHT )
			{
				current = current->right;
			}

			count--;
		}

		if( parent != NULL )
		{
			if( bit == BT_LEFT )
			{
				parent->left = NULL;
			}
			else if( bit == BT_RIGHT )
			{
				parent->right = NULL;
			}
		}
		else
		{
			btree->root = NULL;
		}

		ret = current;

		btree->count = btree->count - recursive_count(ret);
	}

	return ret;
}

BTreeNode* BTree_Get(BTree* tree, BTPos pos, int count) 
{
	TBTree* btree = (TBTree*)tree;
	BTreeNode* ret = NULL; 
	int bit = 0;

	if( btree != NULL )
	{
		BTreeNode* current = btree->root;

		while( (count > 0) && (current != NULL) )
		{
			bit = pos & 1;
			pos = pos >> 1;

			if( bit == BT_LEFT )
			{
				current = current->left;
			}
			else if( bit == BT_RIGHT )
			{
				current = current->right;
			}

			count--;
		}

		ret = current;
	}

	return ret;
}

BTreeNode* BTree_Root(BTree* tree)
{
	TBTree* btree = (TBTree*)tree;
	BTreeNode* ret = NULL;

	if( btree != NULL )
	{
		ret = btree->root;
	}

	return ret;
}

int BTree_Height(BTree* tree) 
{
	TBTree* btree = (TBTree*)tree;
	int ret = 0;

	if( btree != NULL )
	{
		ret = recursive_height(btree->root);
	}

	return ret;
}

int BTree_Count(BTree* tree) 
{
	TBTree* btree = (TBTree*)tree;
	int ret = 0;

	if( btree != NULL )
	{
		ret = btree->count;
	}

	return ret;
}

int BTree_Degree(BTree* tree) 
{
	TBTree* btree = (TBTree*)tree;
	int ret = 0;

	if( btree != NULL )
	{
		ret = recursive_degree(btree->root);
	}

	return ret;
}

void BTree_Display(BTree* tree, BTree_Printf* pFunc, int gap, char div) 
{
	TBTree* btree = (TBTree*)tree;

	if( btree != NULL )
	{
		recursive_display(btree->root, pFunc, 0, gap, div);
	}
}

主函數:

// 二叉樹.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include "BTree.h"
#include <iostream>

struct Node    //數據結點
{
	BTreeNode header;
	char v;
};

void printf_data(BTreeNode* node)   //打印樹
{
	if( node != NULL )
	{
		printf("%c", ((struct Node*)node)->v);
	}
}

int _tmain(int argc, _TCHAR* argv[])
{

	BTree* tree = BTree_Create();

	struct Node n1 = {{NULL, NULL}, 'A'};
	struct Node n2 = {{NULL, NULL}, 'B'};
	struct Node n3 = {{NULL, NULL}, 'C'};
	struct Node n4 = {{NULL, NULL}, 'D'};
	struct Node n5 = {{NULL, NULL}, 'E'};
	struct Node n6 = {{NULL, NULL}, 'F'};

	BTree_Insert(tree, (BTreeNode*)&n1, 0, 0, 0);
	BTree_Insert(tree, (BTreeNode*)&n2, 0x00, 1, 0);
	BTree_Insert(tree, (BTreeNode*)&n3, 0x01, 1, 0);
	BTree_Insert(tree, (BTreeNode*)&n4, 0x00, 2, 0);
	BTree_Insert(tree, (BTreeNode*)&n5, 0x02, 2, 0);
	BTree_Insert(tree, (BTreeNode*)&n6, 0x02, 3, 0);

	printf("Height: %d\n", BTree_Height(tree));
	printf("Degree: %d\n", BTree_Degree(tree));
	printf("Count: %d\n", BTree_Count(tree));
	printf("Position At (0x02, 2): %c\n", ((struct Node*)BTree_Get(tree, 0x02, 2))->v);
	printf("Full Tree: \n");

	BTree_Display(tree, printf_data, 4, '-');

	//以下是刪除結點位置在0x00的結點後,樹的整體狀態

	BTree_Delete(tree, 0x00, 1);

	printf("After Delete B: \n");
	printf("Height: %d\n", BTree_Height(tree));
	printf("Degree: %d\n", BTree_Degree(tree));
	printf("Count: %d\n", BTree_Count(tree));
	printf("Full Tree: \n");

	BTree_Display(tree, printf_data, 4, '-');

	//以下是清空樹後,樹的整體狀態

	BTree_Clear(tree);

	printf("After Clear: \n");
	printf("Height: %d\n", BTree_Height(tree));
	printf("Degree: %d\n", BTree_Degree(tree));
	printf("Count: %d\n", BTree_Count(tree));

	BTree_Display(tree, printf_data, 4, '-');

	BTree_Destroy(tree);

	system("pause");
	return 0;
}

運行結構:

Height: 4
Degree: 2
Count: 6
Position At (0x02, 2): E
Full Tree:
A
----B
--------D
--------E
------------F
------------
----C
After Delete B:
Height: 2
Degree: 1
Count: 2
Full Tree:
A
----
----C
After Clear:
Height: 0
Degree: 0
Count: 0

請按任意鍵繼續. . .



如有錯誤,望不吝指出呀。


發佈了61 篇原創文章 · 獲贊 18 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章