草庐IT

详细手把手教会二叉树链式结构【数据结构】

鄃鳕 2023-05-07 原文

文章目录

二叉树链式结构的实现

typedef int BinartTreeType;
typedef struct BinarytTreeNode
{
	BinartTreeType data;//节点存放的数据
	struct BinarytTreeNode* left; //指向当前节点的左孩子
	struct BinarytTreeNode* right;//指向当前节点的右孩子

}BTNode;

前序遍历

访问根结点的操作发生在遍历其左右子树之前
简单来说就是 根节点 左子树 右子树

1 2 3 NULL NULL NULL 4 5 NULL NULL 6 NULL NULL

  BTNode* CreateTree()
  {
	  BTNode* node1 = BuyNode(1);
	  BTNode* node2 = BuyNode(2);
	  BTNode* node3 = BuyNode(3);
	  BTNode* node4 = BuyNode(4);
	  BTNode* node5 = BuyNode(5);
	  BTNode* node6 = BuyNode(6);
	  BTNode* node7 = BuyNode(7);

	  node1->left = node2;
	  node1->right = node4;
	  node2->left= node3;
	  node4->left = node5;
	  node4->right = node6;
	  //node3->right = node7;

	  return node1;
  }
  void PreOreder(BTNode* root) //根 左子树 右子树 
  {
	  if (root == NULL)
	  {
		  printf("NULL ");
		  return;
	  }
	  printf("%d ", root->data);
	  PreOreder(root->left);
	  PreOreder(root->right);
  }
  int main()
  {
	  BTNode* root = CreateTree();
	  PreOreder(root);
	  return 0;
  }

从根节点1开始遍历 , 遍历完1这个根节点 ,然后去遍历1这个根节点的左子树(2) ,遍历到节点2时 , 但是节点 2 又被分成根节点 (2)、左子树(3) 、右子树(NULL) 。遍历到节点3时 ,节点3又被分成根节点 (3)、左子树(NULL) 、右子树(NULL) ,对于节点3而言 ,3的左子树(NULL)走完 ,就走节点3的右子树(NULL) , 3这一整棵树作为2的左子树 ,2的左子树走完了 ,就走2的右子树(NULL) , 2的整棵树作为1的左子树, ,2这一整棵树走完了, 就走到1的右子树4 ,但是节点 4 又被分成根节点 (4)、左子树(5) 、右子树(6) ,然后走到4的左子树5 ,但是节点 5 又被分成根节点 (5)、左子树(NULL) 、右子树(NULL) ,5的整棵树作为4的左子树, ,5这一整棵树走完了,就来到了4的右子树(6),但是节点 6又被分成根节点 (6)、左子树(NULL) 、右子树(NULL), 4的左子树,右子树都遍历完了 ,4的这一整棵树也遍历完了,4这一整棵树是作为1的右子树 ,

前序遍历就是将每一个节点不断拆分成 根,左子树 ,右子树的一个过程

前序遍历递归展开图,以左子树为例,右子树并未画出

中序遍历

访问根结点的操作发生在遍历其左右子树之中(间)
简单来说就是 左子树 根节点 右子树

NULL 3 NULL 2 NULL 1 NULL 5 NULL 4 NULL 6 NULL

节点 1被分成根节点 (1)、左子树(2) 、右子树(4) ,先遍历1的左子树2,遇到节点2不能直接访问,得继续拆分 , 节点 2被分成根节点 (2)、左子树(3) 、右子树(NULL) ,遇到节点3,节点3又被分成根节点 (3)、左子树(NULL) 、右子树(NULL) ,那什么样的情况,能直接访问左子树? 遇到空树就可以直接访问,因为空树不能再被拆分,是最小规模的子问题 。 所以第一个访问的是节点3的左子树(NULL) ,再到根节点(3) ,再到3的右子树(NULL) 。3的整棵树作为2的左子树, ,3这一整棵树走完了。2的左子树访问完了 ,就可以访问根节点2了 ,然后到2的右子树(NULL),2的整棵树作为1的左子树, ,2这一整棵树走完了 ,就可以访问根节点1了 ,然后到1的右子树(4) ,遇到节点4不能直接访问,得继续拆分,节点 4 又被分成根节点 (4)、左子树(5) 、右子树(6),遇到节点5不能直接访问,得继续拆分,节点 5 又被分成根节点 (5)、左子树(NULL) 、右子树(NULL) ,然后访问5的左子树(NULL) ,、5(根节点)、5的右子树(NULL),5这一整棵树走完了。4的左子树访问完了 ,就可以访问根节点4了 ,然后到4的右子树(6),遇到节点6不能直接访问,得继续拆分,节点 6又被分成根节点 (6)、左子树(NULL) 、右子树(NULL) ,然后访问6的左子树(NULL) ,、6(根节点)、6的右子树(NULL),6这一整棵树走完了,4的右子树访问完了 , 4这一整棵树作为1的右子树也访问完了

中序遍历访问的第一个一定是NULL ,因为任何一个节点都可以被视作根节点 ,有些书上中序遍历访问的第一个不是NULL ,是因为书上省略了

  BTNode* CreateTree()
  {
	  BTNode* node1 = BuyNode(1);
	  BTNode* node2 = BuyNode(2);
	  BTNode* node3 = BuyNode(3);
	  BTNode* node4 = BuyNode(4);
	  BTNode* node5 = BuyNode(5);
	  BTNode* node6 = BuyNode(6);
	  BTNode* node7 = BuyNode(7);

	  node1->left = node2;
	  node1->right = node4;
	  node2->left= node3;
	  node4->left = node5;
	  node4->right = node6;
	  //node3->right = node7;

	  return node1;
  }
  void PreOreder(BTNode* root) //根 左子树 右子树 
  {
	  if (root == NULL)
	  {
		  printf("NULL ");
		  return;
	  }
	  printf("%d ", root->data);
	  PreOreder(root->left);
	  PreOreder(root->right);
  }
  void InOreder(BTNode* root) //中序遍历 左子树 根 右子树
  {
	  if (root == NULL)
	  {
		  printf("NULL ");
		  return;
	  }
	  InOreder(root->left);
	  printf("%d ", root->data);
	  InOreder(root->right);
  }

  int main()
  {
	  BTNode* root = CreateTree();
	/*  PreOreder(root);*/
	  InOreder(root);
	  PostOreder(root);
	  return 0;
  }

中序遍历递归展开图,以左子树为例,右子树并未画出

后序遍历

访问根结点的操作发生在遍历其左右子树之后
简单来说就是 左子树 右子树 根

NULL NULL 3 NULL 2 NULL NULL 5 NULL NULL 6 4 1

遇到节点1不能直接访问,得继续拆分,节点1又被分成根节点 (1)、左子树(2) 、右子树(4) ,遇到节点2不能直接访问,得继续拆分,节点 2被分成根节点 (2)、左子树(3) 、右子树(NULL) ,遇到节点3不能直接访问,得继续拆分,节点3又被分成根节点 (3)、左子树(NULL) 、右子树(NULL), 先访问3的左子树(NULL) ,再访问3的右子树(NULL) ,然后才到根节点(3),3这一整棵树走完了。2的左子树访问完了 ,再访问2的右子树(NULL)了,然后才到根节点(2)。2的整棵树作为1的左子树, ,2这一整棵树走完了 ,就走到节点1,但是遇到节点1不能直接访问,然后走到1的右子树(4),但是遇到节点4不能直接访问 得继续拆分,节点 4 又被分成根节点 (4)、左子树(5) 、右子树(6),来到4的左子树节点5,还是不能直接访问 ,得继续拆分,节点 5 又被分成根节点 (5)、左子树(NULL) 、右子树(NULL) ,先访问5的左子树(NULL) ,再访问5的右子树(NULL) ,然后才到根节点(5),5这一整棵树走完了。4的左子树访问完了 ,再访问4的右子树(6)了,遇到节点6不能直接访问,得继续拆分,节点 6又被分成根节点 (6)、左子树(NULL) 、右子树(NULL),先访问6的左子树(NULL) ,再访问6的右子树(NULL),然后才到根节点(6),6的整棵树作为4的右子树, ,6这一整棵树走完了 ,就走到节点4, 4的整棵树作为1的右子树, ,4这一整棵树走完了 ,就走到节点1

  BTNode* CreateTree()
  {
	  BTNode* node1 = BuyNode(1);
	  BTNode* node2 = BuyNode(2);
	  BTNode* node3 = BuyNode(3);
	  BTNode* node4 = BuyNode(4);
	  BTNode* node5 = BuyNode(5);
	  BTNode* node6 = BuyNode(6);
	  BTNode* node7 = BuyNode(7);

	  node1->left = node2;
	  node1->right = node4;
	  node2->left= node3;
	  node4->left = node5;
	  node4->right = node6;
	  //node3->right = node7;

	  return node1;
  }
  void PreOreder(BTNode* root) //根 左子树 右子树 
  {
	  if (root == NULL)
	  {
		  printf("NULL ");
		  return;
	  }
	  printf("%d ", root->data);
	  PreOreder(root->left);
	  PreOreder(root->right);
  }
  void InOreder(BTNode* root) //中序遍历 左子树 根 右子树
  {
	  if (root == NULL)
	  {
		  printf("NULL ");
		  return;
	  }
	  InOreder(root->left);
	  printf("%d ", root->data);
	  InOreder(root->right);
  }

  PostOreder(BTNode* root) // 后序遍历 左子树 右子树 根
  {
	  if (root == NULL)
	  {
		  printf("NULL ");
		  return;
	  }
	  PostOreder(root->left);
	  PostOreder(root->right);
	  printf("%d ", root->data);
  }

  int main()
  {
	  BTNode* root = CreateTree();
	/*  PreOreder(root);*/
	  InOreder(root);
	  PostOreder(root);
	  return 0;
  }

层序遍历

1 2 3 4 5 6

层序遍历使用队列先进先出的特性,二叉树的上一层 出队,二叉树的下一层入队

根节点1入队 ,然后1节点出队 ,再把1节点的左孩子2 、右孩子4入队 , 再2节点出队 ,2的左孩子3入队 ,2的右孩子空树 ,空树就不入队了 ,4出队 ,4的左孩子5入队 ,右孩子6入队 ,
最后3出队 ,左右孩子都是空树就不入队了,5出队 ,左右孩子都是空树就不入队了,6出队 ,左右孩子都是空树就不入队了, 当所有节点出队也就结束了

void LevelOrder(BTNode* root) //层序遍历 
{
	
	Queue q;
	QueueInit(&q);
	//遍历 
	//不是空树 
	if (root)
		QueuePush(&q ,root);
	while (!QueueEmpty(&q) )
	{
		
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%d ",front->data);
		 
			if (front->left)//不是空树 入队
		{
			QueuePush(&q, front->left);

		}
		if (front->right) //不是空树 入队
		{
			QueuePush(&q, front->right);

		}

	}

	QueueDestory(&q);
}

树节点个数

采用分治方法

分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。

typedef int BinartTreeType;
typedef struct BinarytTreeNode
{
	BinartTreeType data;//节点存放的数据
	struct BinarytTreeNode* left; //指向当前节点的左孩子
	struct BinarytTreeNode* right;//指向当前节点的右孩子

}BTNode;

BTNode* BuyNode(BinartTreeType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	//扩容成功
	node->data = x;
	node->left = NULL;
	node->right = NULL;

	return node;

}
BTNode* CreateTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);
	BTNode* node7 = BuyNode(7);

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	//node3->right = node7;

	return node1;
}

//int TreeSize(BTNode* root, int* psize)
//{
//	if (root == NULL)
//		return;
//	(*psize)++;
//	TreeSize(root->left, psize);
//	TreeSize(root->right, psize);
//}

int TreeSize(BTNode* root) //分治思想
{
	return root == NULL ? 0 :
			TreeSize(root->left ) 
			+TreeSize(root->right)
			+ 1; //  +1 是加上自己

}

int main()
{
	BTNode* root = CreateTree();
	printf("%d ", TreeSize(root));
	return 0;
}

树的深度

采用分治思想 ,求出最长的那一条
当前树的高度 = 左右子树高度大的+1

typedef int BinartTreeType;
typedef struct BinarytTreeNode
{
	BinartTreeType data;//节点存放的数据
	struct BinarytTreeNode* left; //指向当前节点的左孩子
	struct BinarytTreeNode* right;//指向当前节点的右孩子

}BTNode;

BTNode* BuyNode(BinartTreeType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	//扩容成功
	node->data = x;
	node->left = NULL;
	node->right = NULL;

	return node;

}
BTNode* CreateTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);
	BTNode* node7 = BuyNode(7);

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	//node3->right = node7;

	return node1;
}
//int TreeHight(BTNode* root) //求整棵树的高度
//{
//	if (root == NULL)
//	{
//		return 0;
//	}
//	return TreeHight(root->left) > TreeHight(root->right) 
//		? TreeHight(root->left) + 1: TreeHight(root->right) + 1;
//}

int TreeHeight(BTNode* root)
{
	if( root == NULL)
		return 0;
	 
	int leftHeight = TreeHeight(root->left);
	int rightHeight = TreeHeight(root->right);

	return leftHeight > rightHeight 
		? leftHeight + 1
		: rightHeight + 1;

}

int main()
{
	BTNode* root = CreateTree();
	printf("%d ", TreeHeight(root));

	return 0;
}

第K层节点个数

根的第K层节点个数 = 左子树的第K-1层个数 + 右子树的第K-1 层个数

typedef int BinartTreeType;
typedef struct BinarytTreeNode
{
	BinartTreeType data;//节点存放的数据
	struct BinarytTreeNode* left; //指向当前节点的左孩子
	struct BinarytTreeNode* right;//指向当前节点的右孩子

}BTNode;

BTNode* BuyNode(BinartTreeType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	//扩容成功
	node->data = x;
	node->left = NULL;
	node->right = NULL;

	return node;

}
BTNode* CreateTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);
	BTNode* node7 = BuyNode(7);

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	node3->right = node7;

	return node1;
}
int TreeKlevel(BTNode* root,int k) //第K层节点个数
{
	if (root == NULL)
		return 0;
	if (k == 1)  // 隐含root != NULL , 此时是第K层
		return 1;
	//左子树 K-1 个数 + 右子树K-1 个数 
	int leftKlevel = TreeKlevel(root->left, k - 1);
	int rightKlevel = TreeKlevel(root->right, k - 1);
	return leftKlevel + rightKlevel;

}
int main()
{
	BTNode* root = CreateTree();
	int k = 3;
	printf("%d ", TreeKlevel(root,k));

	return 0;
}

查找二叉树中的元素

BTNode* BinaryTreeFind(BTNode* root , BinartTreeType x )//查找二叉树中的元素
{
	//左子树 右子树 根
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	//保存
	BTNode* lret = BinaryTreeFind(root->left, x);
	if (lret)
		return lret;
	//保存
	BTNode* rret = BinaryTreeFind(root->right, x);
	if (rret)
		return rret;
	//没有找到
	return NULL;
}

递归展开图:


完整代码
Test.c

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Queue.h"
typedef int BinartTreeType;
typedef struct BinarytTreeNode
{
	BinartTreeType data;//节点存放的数据
	struct BinarytTreeNode* left; //指向当前节点的左孩子
	struct BinarytTreeNode* right;//指向当前节点的右孩子

}BTNode;

BTNode* BuyNode(BinartTreeType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		printf("malloc fail");
		exit(-1);
	}
	//扩容成功
	node->data = x;
	node->left = NULL;
	node->right = NULL;

	return node;

}
BTNode* CreateTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);
	BTNode* node7 = BuyNode(7);

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	node3->right = node7;

	return node1;
}
//void PreOreder(BTNode* root) //根 左子树 右子树 
//{
//	if (root == NULL)
//	{
//		printf("NULL ");
//		return;
//	}
//	printf("%d ", root->data);
//	PreOreder(root->left);
//	PreOreder(root->right);
//}
//void InOreder(BTNode* root) //中序遍历 左子树 根 右子树
//{
//	if (root == NULL)
//	{
//		printf("NULL ");
//		return;
//	}
//	InOreder(root->left);
//	printf("%d ", root->data);
//	InOreder(root->right);
//}
//
//void PostOreder(BTNode* root) // 后序遍历 左子树 右子树 根
//{
//	if (root == NULL)
//	{
//		printf("NULL ");
//		return;
//	}
//	PostOreder(root->left);
//	PostOreder(root->right);
//	printf("%d ", root->data);
//}
//int TreeSize(BTNode* root, int* psize)
//{
//	if (root == NULL)
//		return;
//	(*psize)++;
//	TreeSize(root->left, psize);
//	TreeSize(root->right, psize);
//}
//
//int TreeSize(BTNode* root) //分治思想
//{
//	return root == NULL ? 0 :
//		TreeSize(root->left)
//		+ TreeSize(root->right)
//		+ 1; // +1 是加上自己
//
//}

//int TreeHight(BTNode* root) //求整棵树的高度
//{
//	if (root == NULL)
//	{
//		return 0;
//	}
//	return TreeHight(root->left) > TreeHight(root->right) 
//		? TreeHight(root->left) + 1: TreeHight(root->right) + 1;
//}

//int TreeHeight(BTNode* root)
//{
//	if( root == NULL)
//		return 0;
//	 
//	int leftHeight = TreeHeight(root->left);
//	int rightHeight = TreeHeight(root->right);
//
//	return leftHeight > rightHeight 
//		? leftHeight + 1
//		: rightHeight + 1;
//
//}
//int TreeKlevel(BTNode* root,int k) //第K层节点个数
//{
//	if (root == NULL)
//		return 0;
//	if (k == 1)  // 隐含root != NULL , 此时是第K层
//		return 1;
//	//左子树 K-1 个数 + 右子树K-1 个数 
//	int leftKlevel = TreeKlevel(root->left, k - 1);
//	int rightKlevel = TreeKlevel(root->right, k - 1);
//	return leftKlevel + rightKlevel;
//
//}

BTNode* BinaryTreeFind(BTNode* root , BinartTreeType x )//查找二叉树中的元素
{
	//左子树 右子树 根
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	//保存
	BTNode* lret = BinaryTreeFind(root->left, x);
	if (lret)
		return lret;
	//保存
	BTNode* rret = BinaryTreeFind(root->right, x);
	if (rret)
		return rret;
	//没有找到
	return NULL;
}

void LevelOrder(BTNode* root) //层序遍历 
{
	
	Queue q;
	QueueInit(&q);
	//遍历 
	//不是空树 
	if (root)
		QueuePush(&q ,root);
	while (!QueueEmpty(&q) )
	{
		
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%d ",front->data);
		 
			if (front->left)//不是空树 入队
		{
			QueuePush(&q, front->left);

		}
		if (front->right) //不是空树 入队
		{
			QueuePush(&q, front->right);

		}

	}

	QueueDestory(&q);
}

int main()
{
	BTNode* root = CreateTree();
	/*  PreOreder(root);*/
	 // InOreder(root);
	 // PostOreder(root);

	//int size1 = 0;
	//TreeSize(root, &size1);
	//printf("%d ", size1);
	//printf("%d ", TreeSize(root));
	//printf("%d ", TreeHeight(root));
	/*int k = 3;
	printf("%d ", TreeKlevel(root,k));*/
	/*printf("%p ", BinaryTreeFind(root, 2));*/
	LevelOrder(root);
	return 0;
}

Queue.h

#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>

typedef struct BinarytTreeNode *  QueueNodeTypeData;

typedef struct  QueueNode
{
	struct  QueueNode* next;
	QueueNodeTypeData data;
}QueueNodeType;

typedef struct Queue
{
	QueueNodeType * tail; // 队尾
	QueueNodeType * head; //队头
	int size; 
} Queue;  // 链式结构:表示队列


void QueueInit(Queue* pq);  // 初始化  

void QueueDestory(Queue* pq); //队列的销毁

void QueuePush(Queue* pq , QueueNodeTypeData x );  // 队尾入队列

void QueuePop(Queue* pq); //队头出队列

int QueueSize(Queue* pq);//获取队列中有效元素个数

bool QueueEmpty(Queue* pq); // 判断队列是否为空 

QueueNodeTypeData QueueFront(Queue* pq); //获取队列头部元素

QueueNodeTypeData QueueBack(Queue* pq); //获取队列尾部元素

Queue.c

#include"Queue.h"
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

void QueueDestory(Queue* pq) //队列的销毁
{
	assert(pq);
	QueueNodeType * cur = pq->head;
	
	//遍历 
	while (cur)
	{
		QueueNodeType* next = cur->next;  //保存下一个节点的地址
		free(cur); //释放当前节点
		cur = next; 
	}
	  pq->tail = pq->head = NULL;
	pq->size = 0;
}
void QueuePush(Queue* pq, QueueNodeTypeData x) // 入队 
{
	assert(pq);
	QueueNodeType* newnode =(QueueNodeType*) malloc( sizeof(QueueNodeType) );
	if (newnode == NULL)
	{
		printf(" malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	//扩容成功

	//第一次入队
	if ( pq->head == NULL)
	{
   		assert(pq->tail == NULL);   //pq->head ==NULL , pq->tail != NULL ,就是出问题了
		pq->tail = pq->head = newnode;
	}
	else //非第一次入队
	{
		pq->tail->next = newnode; // 类似尾插
		pq->tail = newnode; // 更新tail 指针
	}
	pq->size++;
}
void QueuePop(Queue* pq) //队头出队列
{
	assert(pq);
	assert(pq->head != NULL); 

	//只有一个节点

	if (pq->head->next == NULL) 
	{
		free(pq->tail);  //出队
		pq->tail = pq->head = NULL;
	}
	// 多个节点
	else
	{
		QueueNodeType* next = pq->head->next; // 保存下一个节点的地址 
		free(pq->head); // 出队
		pq->head = NULL;
		pq->head = next;  //更新pq->head ,往后走 
	}
	pq->size--;
}


int QueueSize(Queue* pq)//获取队列中有效元素个数
{
	assert(pq);
	
	return pq->size;
}

//bool QueueEmpty(Queue* pq) // 判断队列是否为空 
//{
//	assert(pq);
//
//	if (pq->head == 0)
//	{
//		return true;
//	}
//	else
//	{
//		return false;
//	}
//}

bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

QueueNodeTypeData QueueFront(Queue* pq) //获取队列头部元素
{
	assert(pq);
	assert(!QueueEmpty(pq)); //防止队列为空
	
	return pq->head->data;

}

QueueNodeTypeData QueueBack(Queue* pq) //获取队列尾部元素
{
	assert(pq);
	assert(!QueueEmpty(pq)); //防止队列为空

	return pq->tail->data;
}

如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注
你们的每一次支持都将转化为我前进的动力!!!

有关详细手把手教会二叉树链式结构【数据结构】的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  3. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  4. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  5. ruby-on-rails - 一般建议和推荐的文件夹结构 - Sinatra - 2

    您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应

  6. ruby - 如何在 ruby​​ 中复制目录结构,不包括某些文件扩展名 - 2

    我想编写一个ruby​​脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"

  7. ruby - 在 Ruby 中实现二叉树 - 2

    我一直在尝试在Ruby中实现BinaryTree类,但我得到了stackleveltoodeep错误,尽管我似乎没有在该特定代码段中使用任何递归:1.classBinaryTree2.includeEnumerable3.4.attr_accessor:value5.6.definitialize(value=nil)7.@value=value8.@left=BinaryTree.new#stackleveltoodeephere9.@right=BinaryTree.new#andhere10.end11.12.defempty?13.(self.value==nil)?true:

  8. ruby-on-rails - 在 Rails 中存储(结构化)配置数据的位置 - 2

    对于我正在编写的Rails3应用程序,我正在考虑从本地文件系统上的XML、YAML或JSON文件中读取一些配置数据。重点是:我应该把这些文件放在哪里?Rails应用程序中是否有用于存储此类内容的默认位置?附带说明一下,我的应用程序部署在Heroku上。 最佳答案 我经常做的是:如果文件是通用配置文件:我在目录/config中创建一个YAML文件,每个环境有一个上层key如果我为每个环境(大项目)创建一个文件:我为每个环境创建一个YAML并将它们存储在/config/environments/然后我在加载YAML的地方创建了一个初始化

  9. ruby-on-rails -/usr/local/lib/libz.1.dylib,文件是为 i386 构建的,它不是被链接的体系结构 (x86_64) - 2

    在我的mac上安装几个东西时遇到这个问题,我认为这个问题来自将我的豹子升级到雪豹。我认为这个问题也与macports有关。/usr/local/lib/libz.1.dylib,filewasbuiltfori386whichisnotthearchitecturebeinglinked(x86_64)有什么想法吗?更新更具体地说,这发生在安装nokogirigem时日志看起来像:xslt_stylesheet.c:127:warning:passingargument1of‘Nokogiri_wrap_xml_document’withdifferentwidthduetoproto

  10. 100个python算法超详细讲解:画直线 - 2

    1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva

随机推荐