数据结构___二叉树___链式___基本操作___创建和遍历

版权声明:私藏源代码是违反人性的罪恶行为!博客转载无需告知,学无止境。 https://blog.csdn.net/qq_41822235/article/details/86484063

二叉树的种种操作大全 

一、二叉树的创建

create binary tree

预定义类型及结构设计: 

typedef char TElemType;
typedef struct BiTNode
{
	TElemType data;
	BiTNode*leftChild, *rightChild;
}BiTNode, *BiTree;

 举例将用到的二叉树:

  • 先序 A B C D E F G H
  • 中序 C B E D F A G H
  • 后序 C E F D B H G A

1.1 先序_带标记

以#作为空树

BiTNode *buyNode()    //申请一个结点
{
	BiTNode *pNode = new BiTNode;
	assert(NULL != pNode);
	memset(pNode, 0, sizeof(BiTNode));
	return pNode;
}

//按先序次序输入二叉树中结点的值(一个字符),#记为空树
void CreateBiTree(BiTree &T,const TElemType *&str)
{
	if (*str != '#')
	{
		T = buyNode();
		T->data = *str;
		CreateBiTree(T->leftChild, ++str);
		CreateBiTree(T->rightChild, ++str);
	}
}

中序序列是一定要存在的,不然无法确定二叉树。 

1.2 先序和中序

算法如下:

  • 在先序序列中取出根结点,到中序序列中找到根结点,这一过程可封装为findPos;
  • 分别对先序、中序序列进行划分,确定左右子树,缩减问题规模,进行处理。——分治法思想的精髓所在。

编程小技巧,将一个函数API实现只进行参数合法性检查,在函数体内部转调其他函数。 

static int findPos(TElemType pe, const TElemType *istr, int n) //找出先序最左边的元素在中序中的位置。
{
	int pos = -1;
	for (int i = 0; i < n; ++i)
	{
		if (pe == istr[i])
		{
			pos = i;
			break;
		}
	}
	return pos;
}

//先序和中序事务处理,不负责参数合法性检查,只实现以PI方法创建二叉树
static BiTree CreateBiTree_PI_call(const TElemType *pstr, const TElemType *istr, int n)    
{
	TElemType pivotkey = pstr[0];
	int pos = findPos(pivotkey, istr, n);
	if (pos == -1)
		return NULL;
	BiTNode *s = buyNode();
	s->data = pivotkey;

	s->leftChild = CreateBiTree_PI_call(pstr+1,istr,pos);
	s->rightChild = CreateBiTree_PI_call(pstr+pos+1,istr+pos+1,n-pos-1);
	return s;
}

//先序和中序逻辑判断
BiTree CreateBiTree_PI(const TElemType *pstr, const TElemType *istr, int n)
{
	if (pstr == NULL || istr == NULL || n < 1)
		return NULL;
	else
		return CreateBiTree_PI_call(pstr, istr, n);
}

测试用例: 

扫描二维码关注公众号,回复: 4947135 查看本文章
int main()
{
	const TElemType *pstr = "ABCDEFGH";
	const TElemType *istr = "CBEDFAGH";
	int n = strlen(pstr);
	BiTree bt = CreateBiTree_PI(pstr, istr, n);
	PreOrderTraverse(bt, Visit);
	return 0;
}

1.3 中序和后序

算法如下

  • 从后序序列中取出当前树的根结点,到中序序列中找到对应位置。
  • 根据中序序列的特点,根结点的左右分别是左子树部分和有子树部分。

虽然是递归求解,但我们应该层次分析问题 。从经验来看,递归问题我们只需要考虑一层就是了。

//按照后序序列找到根结点在中序序列中的位置。
static int findPos_IS(TElemType se, const TElemType *istr)
{
	int pos = -1;
	int n = strlen(istr);
	for (int i = 0; i < n; ++i)
	{
		if (se == istr[i])
		{
			pos = i;
			break;
		}
	}
	return pos;
}

//istr---中序序列;sstr---后序序列;n---当前序列包含的元素个数
static BiTree CreateBinaryTree_IS_call(const TElemType *istr, const TElemType *sstr, int n)
{
	BiTree root = NULL;
	if (n > 0)	//当前序列中的元素个数
	{
		root = buyNode();
		root->data = sstr[n - 1];
		int pos = findPos_IS(root->data, istr);
		if (pos == -1)	//没有找到证明中序和后序序列不匹配,不能确定二叉树,应该终止程序
			exit(1);
		root->leftChild = CreateBinaryTree_IS_call(istr, sstr, pos);
		root->rightChild = CreateBinaryTree_IS_call(istr + pos + 1, sstr + pos, n - pos - 1);
	}
	return root;
}

//API:根据用户输入的中序序列和后序序列建立二叉树。
BiTree CreateBinary_IS(const TElemType *istr, const TElemType *sstr)
{
	int ni = strlen(istr);
	int ns = strlen(sstr);
	if (istr == NULL || sstr == NULL || ni != ns)
		return NULL;
	else
		return CreateBinaryTree_IS_call(istr, sstr, ni);
}

 测试用例:

int main()
{
	const TElemType* istr = "CBEDFAGH";	//中序序列CBEDFAGH
	const TElemType* sstr = "CEFDBHGA";	//后序序列CEFDBHGA
	BiTree root = CreateBinary_IS(istr, sstr);
	PreOrderTraverse(root,Visit);
	return 0;
}

二、二叉树的遍历

traversing binary tree

如何按某条搜索路径寻访树中的每个结点,使得每个结点均被访问一次,而且仅被访问一次。“访问”的含义很广,可以是对结点做各种处理,如输出结点的信息等。若限定先左后右,则只有DLR先序遍历、LDR中序遍历、LRD后序遍历三种。

2.1 先序

prefix-order

  • 若二叉树为空,则空操作;否则
  • 访问根结点;先序遍历左子树;先序遍历右子树。
void Visit(TElemType e)    //访问元素操作
{
	cout << e<<" ";
	fflush(stdout);
}

//先序遍历---DLR
void PreOrderTraverse(BiTree &T, void(*Visit)(TElemType e))
{
	if (T != NULL)
	{
		Visit(T->data);
		PreOrderTraverse(T->leftChild, Visit);	//L
		PreOrderTraverse(T->rightChild, Visit);	//R
	}
}

测试用例: 

int main()
{
	BiTree bt;
	const TElemType *str = { "ABC##DE##F##G#H##" };
	CreateBiTree(bt,str);    //按照先序创建二叉树
	PreOrderTraverse(bt, Visit);    //按照先序遍历二叉树
	return 0;
}

 三种遍历方式会一种触类旁通就会其余两种,中序和后序就不贴代码了。 

2.2 中序

infix-order

中序遍历实际上是一个结点进栈和出栈的过程。二叉树的形态确定了其结点进栈和出栈的顺序,也确定了其结点的中序序列。

图2-2 中序遍历时进栈和出栈的过程

2.3 后序

sufix-order

2.4 层序

猜你喜欢

转载自blog.csdn.net/qq_41822235/article/details/86484063