数据结构——二叉树

目录

1.树的结构及概念

 1.1  树的定义:

 1.2  树的一些相关概念

2.二叉树的概念和结构

  2.1 二叉树的定义:

  2.2  两个特殊的二叉树:

  2.3  二叉树的一些性质:

3.大堆与小堆:

 3.1  大堆与小堆的概念:

 3.2  堆的实现(顺序结构)

        3.2.1  堆的结构:

        3.2.2  堆的初始化:

        3.2.3   堆的释放(防止内存泄漏):

        3.2.4  堆的核心代码之一 ——向上调整算法:

        3.2.5  堆的插入:

        3.2.6 堆的另一个核心代码——向下调整算法

        3.2.7 堆的删除数据:

        3.2.8 堆的最顶数据:

        3.2.9 堆中元素的总数:

        3.2.10:判断堆是否为空:

4.二叉树的链式结构

4.1 前 、中、后序遍历:

4.2 二叉树的实现

4.2.1 二叉树的链式结构:

4.2.2 二叉树的初始化:

4.2.3 二叉树的销毁:

4.2.4 二叉树的前、中、后序遍历:

4.2.5 求二叉树结点个数:

4.2.6  求叶子结点个数:

4.2.7 求树的高度或者深度:

4.2.8  求第k层结点的个数

4.2.9  寻找二叉树中某个x的值结点

4.2.10 层序遍历:

         4.2.11  判断是否为完全二叉树


1.树的结构及概念

 1.1  树的定义:

         数据结构中的树是一种非线性的数据结构,它是由nn>=0)个有限结点组成一个具有层次关系的集合。我们把它叫做树的原因它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的
     下面是树的图形:
  

     需要注意的是:在树形结构中,不能存在任意的两个子树有任何的交集,否则就不能叫做树了。

   1.2  树的一些相关概念

 

    节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的度为6

    叶子结点:度为0的节点称为叶节点; 如上图:BCHI等节点为称为叶节点

     树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6

2.二叉树的概念和结构

  2.1 二叉树的定义:

       树的度最大只能为2的树叫做二叉树,二叉树最多可以有两个孩子,分别为左孩子和右孩子

下面为二叉树的结构示意图:

    

  2.2  两个特殊的二叉树:

            (1) 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,那么这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^h)-1个。

            (2)完全二叉树:完全二叉树是要求从第1个结点到第n个结点必须满足依次从上到下、从左到右的顺序依次一一插入,最后一层可以不满,但必须从左到右依次插入,中间不能断开。注意:满二叉树是一种特殊的完全二叉树。

 2.3  二叉树的一些性质:

        1. 若规定根节点的层数为1,则一棵非空二叉树的i层上最多有2^(i-1)个结点.

        2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是(2^h)-1个结点。
.
        3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0, 度为2的分支结点个数为n2,则有
            n0=n2 +1.
        4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度h对应为h=log2(n+1)。

3.大堆与小堆:

   3.1  大堆与小堆的概念:

         大堆:堆中某个节点的值总是不大于其父节点的值,叫做大堆。

          小堆:堆中某个节点的值总是不小于其父节点的值,叫做小堆。     

                    大堆                                                                                小堆

 3.2  堆的实现(顺序结构)

        3.2.1  堆的结构:

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

        3.2.2  堆的初始化:

void HeapInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->capacity = php->size = 0;
}

        3.2.3   堆的释放(防止内存泄漏):

void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->capacity = php->size = 0;
}

        3.2.4  堆的核心代码之一 ——向上调整算法:

//建大堆(如果要小堆,把大于号改成小于号即可)
void Sawp(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
void Adjustup(HPDataType* a,int child)
{
	int parents = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parents]) //如果要建小堆需要把>变成<
		{
			Sawp(&a[parents], &a[child]);
			child = parents;
			parents= (child - 1) / 2;
		}
		else
		{
			break;
		}
	}

}

        3.2.5  堆的插入:

void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	//扩容
	if (php->capacity == php->size)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->size] = x;
	php->size++;
	 //大堆(
	Adjustup(php->a, php->size - 1);
}

        3.2.6 堆的另一个核心代码——向下调整算法

void Adjustdown(HPDataType* a,int n, int parents)
{
	int child = (parents * 2) + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] < a[child])
		{
			child++;
		}
		if (a[child] < a[parents])
		{
			Sawp(&a[child], &a[parents]);
			parents = child;
			child= (parents * 2) + 1;
		}
		else
		{
			break;
		}
	}
}

        3.2.7 堆的删除数据:

void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	//大堆
	Sawp(&php->a[0], &php->a[php->size - 1]);
	php->size--;
	Adjustdown(php->a,php->size, 0);
}

        3.2.8 堆的最顶数据:

HPDataType HeapTok(HP* php)
{
	assert(php);
	assert(php->size > 0);
	return php->a[0];
}

        3.2.9 堆中元素的总数:



int HeapSize(HP* php)
{
	assert(php);
	return php->size;
}

        3.2.10:判断堆是否为空:



bool HeapEmpty(HP* php)
{
	assert(php);
	return php->size == 0;
}

4.二叉树的链式结构

4.1 前 、中、后序遍历:

     前序遍历就是 :先根  再左子树  后右子树

     所以,依据上图前序遍历的结果为: 1  2  3 null  null  null  4  5  null  null  6  null  null

     中序遍历就是 :先左子树   再根 后右子树

        

     中序的遍历结果就是 null 3 null 2  null  1 null 5 null  4 null  6 null

     后序遍历就是 :先左子树  再右子树  后根

     后序的遍历结果就是:null  null  3 null  2  null  null  5 null  null  6  4  1

     层序遍历就是:从一层开始,每层从左到右,一层一层走

     层序的遍历结果就是: 1  2  4  3  null 5  6

4.2 二叉树的实现

4.2.1 二叉树的链式结构:

typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct  BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BT;

4.2.2 二叉树的初始化:

BT* BTbuyNode(int x)
{
	BT* newnode = (BT*)malloc(sizeof(BT));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->left = NULL;
	newnode->right = NULL;
	return newnode;
}

4.2.3 二叉树的销毁:

void TreeDestroy(BT* root)
{
	if (root == NULL)
		return;
	TreeDestroy(root->left);
	TreeDestroy(root->right);
	free(root);
}

4.2.4 二叉树的前、中、后序遍历:

//前序
void PrveOrder(BT* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->data);
	PrveOrder(root->left);
	PrveOrder(root->right);
}

//中序
void InOrder(BT* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}

//后序
void PostOrder(BT* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%d ", root->data);
}

4.2.5 求二叉树结点个数:

//求结点个数
int TreeSize(BT* root)
{
	/*if (root == NULL)
		return 0;
	int size = TreeSize(root->left) + TreeSize(root->right)+1;
	return size;*/
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

4.2.6  求叶子结点个数:

//求叶子节点的个数
int BTLeafSize(BT* root)
{
	if (root == NULL)
		return 0;
	if (root->left == NULL && root->right == NULL)
		return 1;
	return BTLeafSize(root->left) + BTLeafSize(root->right);

}

4.2.7 求树的高度或者深度:

//求树的高度或者是深度
int BTTreeHight(BT* root)
{
	if (root == NULL)
		return 0;
	int leftHight = BTTreeHight(root->left);
	int rightHight = BTTreeHight(root->right);
	return leftHight > rightHight ? leftHight + 1 : rightHight + 1;
}

4.2.8  求第k层结点的个数

//求第k层结点的个数
int BTTreeNode(BT* root, int k)
{
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return BTTreeNode(root->left, k - 1) + BTTreeNode(root->right, k - 1);
}

4.2.9  寻找二叉树中某个x的值结点

//寻找x的结点
BT* TreeFind(BT* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	BT* left = TreeFind(root->left, x);
	if (left)
		return left;
	BT* right = TreeFind(root->right, x);
	if (right)
		return right;
	return NULL;
}

4.2.10 层序遍历:

//层序遍历
void LevelOrder(BT* root)
{
	QNode q;
	QueueInit(&q);
	if (root !=NULL)
	{
		QueuePush(&q, root);
	}
	while (QueueEmpty(&q) ==NULL)
	{
		
		BT* front = QueueFront(&q);
		printf("%d", front->data);
		QueuePop(&q);
		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}

	}
	printf("\n");
	Destroy(&q);
}

4.2.11  判断是否为完全二叉树

//判断是否为完全二叉树
int TreeComplete(BT* root)
{
	QNode q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BT* front = QueueFront(&q);
		QueuePop(&q);
		if (front == NULL)
		{
			break;
		}
		else
		{
			QueuePush(&q, front->left);
			QueuePush(&q, front->right);
		}
	}
	//出到空以后,如果后面全是空,则是完全二叉树
	while (!QueueEmpty(&q))
	{
		BT* front = QueueFront(&q);
		QueuePop(&q);

		if (front != NULL)
		{
			Destroy(&q);
			return false;
		}
	}
	Destroy(&q);
	return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值