二叉树的创建及其遍历

17 篇文章 0 订阅

https://www.github.com/wangzhijun_0224/AlgorithmStudy.git

.h文件:

#ifndef _DS_CHARPTER05_H_
#define _DS_CHARPTER05_H_

/*************************************************************************************************/
// 二叉树的结点抽象
#define BTREE_HAVE_PARENT		1

typedef struct treenode* tlink;
tlink  tlink_new_tnode(int item_size, void* pitem);	        // 获取一个节点,并将pitem所指向的item拷贝到节点中
void   tlink_get_item(tlink p, int item_size, void *pitem);	// 获取节点的item数据
void   tlink_insert_left(tlink p, tlink newnode);			// 将newnode插入到p的左儿子上
void   tlink_insert_right(tlink p, tlink newnode);			// 将newnode插入到p的右儿子上
void   tlink_insert_both(tlink p, tlink left, tlink right);
#if BTREE_HAVE_PARENT
tlink  tlink_get_parent(tlink p);
#endif
tlink  tlink_get_lchild(tlink p);
tlink  tlink_get_rchild(tlink p);
tlink* tlink_get_lchild_addr(tlink p);
tlink* tlink_get_rchild_addr(tlink p);

/*************************************************************************************************/
// 二叉树抽象
typedef struct binary_tree* btree;

btree btree_open(int item_size);	// 创建一个空树
void btree_close(btree bt);
int btree_is_empty(btree bt);		// 判断树是否为空
void btree_make_btree(btree bt, void *pitem, void* penditem);
void btree_get_item(btree bt, tlink root, void *pitem);	// 获取以root为根结点的根节点数据
tlink btree_get_root(btree bt);
#if BTREE_HAVE_PARENT
tlink btree_get_parent(btree bt, tlink root);	// 获取root节点的父节点
#endif
tlink btree_get_lchild(btree bt, tlink root);	// 获取以root为根节点的左子树
tlink btree_get_rchild(btree bt, tlink root);	// 获取以root为根节点的右子树

int btree_preorder_recursion(btree bt, void* pitem);     // 递归版前序遍历树,结果存放在pitem数组中,返回值为树中元素个数
int btree_inorder_recursion(btree bt, void* pitem);      // 递归版中序遍历树,结果存放在pitem数组中,返回值为树中元素个数
int btree_postorder_recursion(btree bt, void* pitem);    // 递归版后序遍历树,结果存放在pitem数组中,返回值为树中元素个数

int btree_preorder_norecursion(btree bt, void* pitem);   // 非递归版前序遍历树,结果存放在pitem数组中,返回值为树中元素个数
int btree_preorder_norecursion2(btree bt, void* pitem);  // 非递归版前序遍历树,另一种方法
int btree_inorder_norecursion(btree bt, void* pitem);    // 非递归版中序遍历树,结果存放在pitem数组中,返回值为树中元素个数
int btree_postorder_norecursion(btree bt, void* pitem);  // 非递归版后序遍历树,结果存放在pitem数组中,返回值为树中元素个数
int btree_postorder_norecursion2(btree bt, void* pitem); // 非递归版后序遍历树,另一种方法
int btree_levelorder(btree bt, void* pitem);             // 层序遍历树,同层从左至右
int btree_levelorderR(btree bt, void* pitem);            // 层序遍历树,同层从右至左
#endif


.c文件:

#include "DS_charpter04.h"  // stack, queue

#include "DS_charpter05.h"

#include <stdlib.h>
#include <assert.h>
#include <string.h>
/*************************************************************************************************/
/***********************************************************************************
单链表节点抽象
***********************************************************************************/
// 不完全类型,申请节点的空间是需要加上item的大小
struct treenode{ 
#if BTREE_HAVE_PARENT
tlink parent;
#endif
tlink left, right; 
};

tlink  tlink_new_tnode(int item_size, void* pitem)
{
	tlink newnode = (tlink)malloc(sizeof(*newnode) + item_size);
	void* dst;

	if (NULL != newnode)
	{
	#if BTREE_HAVE_PARENT
		newnode->parent = NULL;
	#endif
		newnode->left = newnode->right = NULL;
		dst = (char *)newnode + sizeof(*newnode);
		memcpy(dst, pitem, item_size);
	}

	return newnode;
}

void   tlink_get_item(tlink p, int item_size, void *pitem)
{
	assert(NULL != p);
	assert(NULL != pitem);

	void *src = (char *)p + sizeof(*p);
	memcpy(pitem, src, item_size);
}

void   tlink_insert_left(tlink p, tlink newnode)
{
#if BTREE_HAVE_PARENT
	if (newnode != NULL) newnode->parent = p;
#endif
	p->left = newnode;
}

void   tlink_insert_right(tlink p, tlink newnode)
{
#if BTREE_HAVE_PARENT
	if (newnode != NULL) newnode->parent = p;
#endif
	p->right = newnode;
}

void tlink_insert_both(tlink p, tlink left, tlink right)
{
#if BTREE_HAVE_PARENT
	if (left != NULL)	left->parent = p;
	if (right != NULL)	right->parent = p;
#endif

	p->left = left;
	p->right = right;


}
#if BTREE_HAVE_PARENT
tlink  tlink_get_parent(tlink p)
{
	return p->parent;
}
#endif
tlink  tlink_get_lchild(tlink p)
{
	return p->left;
}
tlink  tlink_get_rchild(tlink p)
{
	return p->right;
}

tlink* tlink_get_lchild_addr(tlink p)
{
	return &(p->left);
}
tlink* tlink_get_rchild_addr(tlink p)
{
	return &(p->right);
}

/*************************************************************************************************/
// 二叉树抽象
struct binary_tree
{
	tlink root;
	int item_size;
};

btree btree_open(int item_size)
{
	assert(item_size > 0);

	btree bt = (btree)malloc(sizeof(*bt));
	if (NULL == bt) return bt;

	bt->item_size = item_size;
	bt->root = NULL;

	return bt;
}

static void btree_del(tlink root)
{
	if (NULL != root)
	{
		btree_del(root->left);
		btree_del(root->right);
		free(root);
	}
}

void btree_close(btree bt)
{
	btree_del(bt->root);

	free(bt);
}

int btree_is_empty(btree bt)
{
	assert(NULL != bt);

	return (bt->root == NULL);
}

#if BTREE_HAVE_PARENT
static int btree_create_p(tlink parent, tlink *root, void* pitem, int* pindex, int item_size, void* enditem)
{
	void* pcuritem = (char*)pitem + (*pindex)*item_size;

	if (0 == memcmp(pcuritem, enditem, item_size))
	{
		return 0;
	}

	*root = tlink_new_tnode(item_size, pcuritem);
	if (NULL == *root)  return 0;

	(*root)->parent = parent;
	
	(*pindex)++;
	btree_create_p(*root, tlink_get_lchild_addr(*root), pitem, pindex, item_size, enditem);
	(*pindex)++;
	btree_create_p(*root, tlink_get_rchild_addr(*root), pitem, pindex, item_size, enditem);
	return 1;
}
#else
static int btree_create(tlink *root, void* pitem, int* pindex, int item_size, void* enditem)
{
	void* pcuritem = (char*)pitem + (*pindex)*item_size;

	if (0 == memcmp(pcuritem, enditem, item_size))
	{
		return 0;
	}

	*root = tlink_new_tnode(item_size, pcuritem);
	if (NULL == *root)  return 0;

	(*pindex)++;
	btree_create(tlink_get_lchild_addr(*root), pitem, pindex, item_size, enditem);
	(*pindex)++;
	btree_create(tlink_get_rchild_addr(*root), pitem, pindex, item_size, enditem);
	return 1;
}
#endif

void btree_make_btree(btree bt, void *pitem, void* penditem)
{
	int index = 0;
	#if BTREE_HAVE_PARENT
	btree_create_p(NULL, &(bt->root), pitem, &index, bt->item_size, penditem); // root's parent is NULL
	#else
	btree_create(&(bt->root), pitem, &index, bt->item_size, penditem);
	#endif
}

void btree_get_item(btree bt, tlink root, void *pitem)
{
	assert(bt != NULL);
	assert(root != NULL);
	assert(pitem != NULL);

	tlink_get_item(root, bt->item_size, pitem);
}
tlink btree_get_root(btree bt)
{
	return bt->root;
}

#if BTREE_HAVE_PARENT
tlink btree_get_parent(btree bt, tlink root)
{
	if (NULL == root)	return NULL;
	else	return tlink_get_parent(root);
}

#endif

tlink btree_get_lchild(btree bt, tlink root)
{
	if (NULL == root)	return NULL;
	else	return tlink_get_lchild(root);
}

tlink btree_get_rchild(btree bt, tlink root)
{
	if (NULL == root)	return NULL;
	else	return tlink_get_rchild(root);
}

/*************************************************************************************************/
/***********************************************************************************
递归版前序遍历: 根节点-左孩子-右孩子的顺序遍历
***********************************************************************************/
static void preorder_recursion(btree bt, tlink root, void* pitem, int* pindex)
{
	char *dst;

	if (NULL != root)
	{
		dst = (char*)pitem + (*pindex)*sizeof(char);
		btree_get_item(bt, root, dst);
		(*pindex)++;
		preorder_recursion(bt, btree_get_lchild(bt, root), pitem, pindex);
		preorder_recursion(bt, btree_get_rchild(bt, root), pitem, pindex);
	}
}

/***********************************************************************************
递归版中序遍历: 左孩子-根节点-右孩子
***********************************************************************************/
static void inorder_recursion(btree bt, tlink root, void* pitem, int* pindex)
{
	char *dst;

	if (NULL != root)
	{
		inorder_recursion(bt, btree_get_lchild(bt, root), pitem, pindex);
		dst = (char*)pitem + (*pindex)*sizeof(char);
		btree_get_item(bt, root, dst);
		(*pindex)++;
		inorder_recursion(bt, btree_get_rchild(bt, root), pitem, pindex);
	}
}

/***********************************************************************************
递归版后序遍历: 左孩子-右孩子-根节点
***********************************************************************************/
static void postorder_recursion(btree bt, tlink root, void* pitem, int* pindex)
{
	char *dst;

	if (NULL != root)
	{
		postorder_recursion(bt, btree_get_lchild(bt, root), pitem, pindex);
		postorder_recursion(bt, btree_get_rchild(bt, root), pitem, pindex);
		dst = (char*)pitem + (*pindex)*sizeof(char);
		btree_get_item(bt, root, dst);
		(*pindex)++;
	}
}

int btree_preorder_recursion(btree bt, void* pitem)
{
	tlink root = NULL;
	int index = 0;
	assert(NULL != bt);
	assert(NULL != pitem);

	root = btree_get_root(bt);

	preorder_recursion(bt, root, pitem, &index);

	return index;
}

int btree_inorder_recursion(btree bt, void* pitem)
{
	tlink root = NULL;
	int index = 0;
	assert(NULL != bt);
	assert(NULL != pitem);

	root = btree_get_root(bt);

	inorder_recursion(bt, root, pitem, &index);

	return index;
}

int btree_postorder_recursion(btree bt, void* pitem)
{
	tlink root = NULL;
	int index = 0;
	assert(NULL != bt);
	assert(NULL != pitem);

	root = btree_get_root(bt);

	postorder_recursion(bt, root, pitem, &index);

	return index;
}

/*************************************************************************************************/
#if (!BTREE_HAVE_PARENT)

/***********************************************************************************
非递归版前序遍历:
根据前序遍历访问的顺序,优先访问根节点,然后再分别访问左孩子和右孩子,即对于任一节点,其可看做是根节点,
因此可直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问完其左子树时,再访问它的右子树。

对于任一结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则从栈中取出栈顶元素,并将栈顶结点的右孩子置为当前的结点P,循环至1);
若不为空,则将P的左孩子置为当前的结点P;
3)直到栈为空,则遍历结束。
***********************************************************************************/
int btree_preorder_norecursion(btree bt, void* pitem)
{
	tlink root = btree_get_root(bt);
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);
	
	stack_slist stk = stack_slist_open(sizeof(root));

	while (1)
	{
		while (NULL != root)
		{
			dst = (char*)pitem + index*sizeof(char);
			btree_get_item(bt, root, dst);
			index++;
			
			stack_slist_insert(stk, &root);
			
			root = btree_get_lchild(bt, root);
		}
		
		if (0 == stack_slist_del(stk, &root)) break;    // 栈为空 
		
		root = btree_get_rchild(bt, root);
	}
	
	stack_slist_close(stk);
	
	return index;
}

#else
/***********************************************************************************
带有parent属性的前序非递归遍历:
对于任一结点root:
1)访问结点root;
2)判断root的左孩子是否为空,若不为空,则将root的左孩子设置为root,循环至1);若为空,则转至3);
3)取root的右孩子,如果root的右孩子不为空,则将root的右孩子设置为root,循环至1);
  若为空,则沿root的parent往上搜索,直到parent为空(则遍历结束)或找到一个parent的右孩子不为root为止,
  将此parent的右孩子设置为root,循环至1)
***********************************************************************************/
int btree_preorder_norecursion(btree bt, void* pitem)
{
	tlink root, left, right, parent;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	for (root = btree_get_root(bt); root != NULL; )
	{
        while (1)
		{
			dst = (char*)pitem + index*sizeof(char);
			btree_get_item(bt, root, dst);
			index++;

			left = btree_get_lchild(bt, root);
			if (NULL == left)	break;
			else	root = left;
		}

		right = btree_get_rchild(bt, root);
		if (NULL == right)	// 右子树遍历完成
		{
			// 沿二叉树往上搜索,直到parent为空或找到一个parent的右节点不为root为止
			parent = tlink_get_parent(root);
			while (NULL != parent && root == btree_get_rchild(bt, parent))
			{
				root = parent;
				parent = tlink_get_parent(parent);
			}
			
			if (NULL != parent) root = btree_get_rchild(bt, parent);
			else break;
				
		}
		else	// 有右子树,遍历右子树
		{
			root = right;
		}
	}
	
	return index;
}
#endif

/***********************************************************************************
非递归版前序遍历2:
***********************************************************************************/
int btree_preorder_norecursion2(btree bt, void* pitem)
{
	tlink root = btree_get_root(bt), tmplink;
	stack_slist stk;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	if (NULL == root)   return 0; // 空节点不入栈

	stk = stack_slist_open(sizeof(root));

	stack_slist_insert(stk, &root);

	while (1)
	{
		if (0 == stack_slist_top(stk, &root))    break;

		dst = (char*)pitem + index*sizeof(char);
		btree_get_item(bt, root, dst);
		index++;

		stack_slist_pop(stk);

		tmplink = btree_get_rchild(bt, root);
		if (NULL != tmplink) stack_slist_insert(stk, &tmplink);

		tmplink = btree_get_lchild(bt, root);
		if (NULL != tmplink) stack_slist_insert(stk, &tmplink);
	}

	stack_slist_close(stk);

	return index;
}

#if (!BTREE_HAVE_PARENT)

/***********************************************************************************
非递归版中序遍历:
根据中序遍历的顺序,对于任一节点,优先访问其左孩子,而左孩子节点又可看做根节点,
然后继续访问其左孩子节点,直到遇到左孩子为空的节点才进行访问,然后按相同的规则访问其右子树。

对于任一结点P:
1)若结点P的左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后循环当前判断;
若P的左孩子为空,则从栈中取出栈顶元素,访问栈顶节点,然后将当前的P设为栈顶节点的右孩子;
3)直到栈为空,则遍历结束。
***********************************************************************************/
int btree_inorder_norecursion(btree bt, void* pitem)
{
	tlink tmplink;
	stack_slist stk;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	tmplink = btree_get_root(bt);
	stk = stack_slist_open(sizeof(tmplink));

	while (1)
	{
		while (tmplink != NULL)
		{
			stack_slist_insert(stk, &tmplink);
			tmplink = btree_get_lchild(bt, tmplink);
		}

		if (0 == stack_slist_del(stk, &tmplink)) break;

		dst = (char*)pitem + index*sizeof(char);
		index++;
		btree_get_item(bt, tmplink, dst);

		tmplink = btree_get_rchild(bt, tmplink);
	}

	stack_slist_close(stk);

	return index;
}
#else
/***********************************************************************************
带有parent属性的中序非递归遍历:
对于任一结点root:
1)判断root的左孩子是否为空,若不为空,则将root的左孩子设置为root,循环本步骤;
  若为空,则转至2);
2)访问节点root,然后判断root的右孩子是否为空,若不为空,则将root的右孩子设置为root,循环至1);
  若为空,则沿root的parent往上搜索,直到parent为空(则遍历结束)或找到一个parent的右孩子不为root为止,
  此时先访问parent的值,再将此parent的右孩子设置为root,循环至1)
***********************************************************************************/
int btree_inorder_norecursion(btree bt, void* pitem)
{
	tlink root, parent, left, right;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	root = btree_get_root(bt);

	while (NULL != root)
	{
		while(1)
		{
			left = btree_get_lchild(bt, root);
			if (NULL == left)	break;	// 左子树遍历完成
			else root = left;
		}

		dst = (char*)pitem + index*sizeof(char);
		index++;
		btree_get_item(bt, root, dst);
			
		right = btree_get_rchild(bt, root);
		if (NULL == right)	
		{
			parent = tlink_get_parent(root);
			while (NULL != parent && root == btree_get_rchild(bt, parent))
			{
				root = parent;
				parent = tlink_get_parent(parent);
			}
			
			if (NULL != parent) 
			{	
				// 遍历p的右子树之前,先访问p
				dst = (char*)pitem + index*sizeof(char);
				index++;
				btree_get_item(bt, parent, dst);
		
				root = btree_get_rchild(bt, parent);
			}
			else break;
				
		}
		else
		{	
			root = right;
		}
	}

	return index;
}
#endif

#if (!BTREE_HAVE_PARENT)
/***********************************************************************************
非递归版后序遍历1:
思路: 对于任一节点P,将其入栈,然后沿其左子树一直往下搜索,直到搜到到美欧左孩子的节点,
此时该节点出现在栈顶,但此时不能将其出栈并访问,因其右孩子还未被访问。所以,接下来
按相同的规则对其右子树进行处理,当访问完其右孩子时,该节点又出现在栈顶,此时
可以将其出栈并访问。
即:每个节点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此,多设置
一个变量标识该节点是否第一次出现在栈顶。
***********************************************************************************/
typedef struct pstorder_stack_item
{
	tlink link;
	int   flag; // 1: 第一次出现在栈顶 0:不是第一次出现在栈顶
}pstorder_stack_item;

int btree_postorder_norecursion(btree bt, void* pitem)
{
	tlink root = btree_get_root(bt);
	pstorder_stack_item stk_item;
	stack_slist stk;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	stk = stack_slist_open(sizeof(stk_item));

	while (1)
	{
		while (root != NULL)
		{
			stk_item.flag = 1;
			stk_item.link = root;
			stack_slist_insert(stk, &stk_item);
			root = btree_get_lchild(bt, root);
		}

		if (0 == stack_slist_del(stk, &stk_item)) break;

		if (1 == stk_item.flag) // 第一次在栈顶
		{
			stk_item.flag = 0;
			stack_slist_insert(stk, &stk_item);
			root = btree_get_rchild(bt, stk_item.link); // 处理右子树
		}
		else   // 第二次在栈顶
		{
			dst = (char*)pitem + index*sizeof(char);
			btree_get_item(bt, stk_item.link, dst);
			index++;
			root = NULL;
		}
	}

	stack_slist_close(stk);

	return index;
}
#else
/***********************************************************************************
带有parent属性的后序非递归遍历:
对于任一结点root:
1)判断root的左孩子是否为空,若不为空,则将root的左孩子设置为root,循环本步骤;
  若为空,则转至2);
2)然后判断root的右孩子是否为空,若不为空,则将root的右孩子设置为root,循环至1);
  若为空,先访问root的值,再沿root的parent往上搜索:
    若root为parent的右节点,则访问parent节点并继续向上搜索;
  若搜索完成后,parent为空,则遍历结束;否则,将root设置为parent的右节点,循环至1);
***********************************************************************************/
int btree_postorder_norecursion(btree bt, void* pitem)
{
	tlink root, parent, left, right;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	root = btree_get_root(bt);

	while (NULL != root)
	{
		while(1)
		{
			left = btree_get_lchild(bt, root);
			if (NULL == left)	break;	// 左子树遍历完成
			else root = left;
		}
			
		right = btree_get_rchild(bt, root);
		if (NULL == right)	
		{
			dst = (char*)pitem + index*sizeof(char);
			index++;
			btree_get_item(bt, root, dst);

			parent = tlink_get_parent(root);
			while (NULL != parent && root == btree_get_rchild(bt, parent))
			{
				dst = (char*)pitem + index*sizeof(char);
				index++;
				btree_get_item(bt, parent, dst);
			
				root = parent;
				parent = tlink_get_parent(parent);
			}
			
			if (NULL != parent) 
			{	
				root = btree_get_rchild(bt, parent);
			}
			else break;
				
		}
		else
		{	
			root = right;
		}
	}

	return index;
}

#endif

/***********************************************************************************
非递归版后序遍历2:
思路:要保证根节点在左孩子和右孩子访问之后才能访问,因此对于任一节点P,先将其入栈。
如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其
左孩子和右孩子都已被访问过了,则同样可以直接访问该节点。若非上述两种情况,则将P
的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面
被访问,左孩子和右孩子都在根节点前面被访问。
***********************************************************************************/
int btree_postorder_norecursion2(btree bt, void* pitem)
{
	tlink root = btree_get_root(bt), tmplink;
	tlink pre = NULL;
	stack_slist stk;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	if (NULL == root)   return 0;

	stk = stack_slist_open(sizeof(root));


	stack_slist_insert(stk, &root);

	while (1)
	{
		if (0 == stack_slist_top(stk, &root))    break;

		if ((NULL == btree_get_lchild(bt, root) && NULL == btree_get_rchild(bt, root))
			|| (NULL != pre && (pre == btree_get_lchild(bt, root) || pre == btree_get_rchild(bt, root)))
			)
		{
			dst = (char*)pitem + index*sizeof(char);
			btree_get_item(bt, root, dst);
			index++;

			stack_slist_pop(stk);
			pre = root;
		}
		else
		{
			tmplink = btree_get_rchild(bt, root);
			if (NULL != tmplink) stack_slist_insert(stk, &tmplink);

			tmplink = btree_get_lchild(bt, root);
			if (NULL != tmplink) stack_slist_insert(stk, &tmplink);
		}
	}

	stack_slist_close(stk);

	return index;
}


/***********************************************************************************
层序遍历二叉树:
一层一层从左向右遍历
***********************************************************************************/
int btree_levelorder(btree bt, void* pitem)
{
	queue_slist qe;
	tlink root = btree_get_root(bt), tmplink;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	if (NULL == root)   return 0;

	qe = queue_slist_open(sizeof(root));

	queue_slist_insert(qe, &root);

	while (1)
	{
		if (0 == queue_slist_del(qe, &root))    break;

		dst = (char*)pitem + index*sizeof(char);
		btree_get_item(bt, root, dst);
		index++;

		tmplink = btree_get_lchild(bt, root);
		if (NULL != tmplink) queue_slist_insert(qe, &tmplink);

		tmplink = btree_get_rchild(bt, root);
		if (NULL != tmplink) queue_slist_insert(qe, &tmplink);
	}

	queue_slist_close(qe);

	return index;
}


/***********************************************************************************
层序遍历二叉树:
一层一层从右向左遍历
***********************************************************************************/
int btree_levelorderR(btree bt, void* pitem)
{
	queue_slist qe;
	tlink root = btree_get_root(bt), tmplink;
	char* dst;
	int index = 0;

	assert(NULL != bt);
	assert(NULL != pitem);

	if (NULL == root)   return 0;

	qe = queue_slist_open(sizeof(root));

	queue_slist_insert(qe, &root);

	while (1)
	{
		if (0 == queue_slist_del(qe, &root))    break;

		dst = (char*)pitem + index*sizeof(char);
		btree_get_item(bt, root, dst);
		index++;

		tmplink = btree_get_rchild(bt, root);
		if (NULL != tmplink) queue_slist_insert(qe, &tmplink);

		tmplink = btree_get_lchild(bt, root);
		if (NULL != tmplink) queue_slist_insert(qe, &tmplink);
	}

	queue_slist_close(qe);

	return index;
}


test.c:

#include "DS_charpter05_test.h"

#include "DS_charpter05.h"


static void create_btree_test(void)
{
/*
树:
	    A
	  /   \
	 B      C
	/ \    / \
     D   E  F   G
    / \
   H   I
*/
	char str[] = { 'A', 'B', 'D', 'H', '\0', '\0', 'I', '\0', '\0', 'E',
		'\0', '\0', 'C', 'F', '\0', '\0', 'G', '\0', '\0' };

	char end_item = '\0';

	btree bt = btree_open(sizeof(char));
	btree_make_btree(bt, str, &end_item);

	tlink root = btree_get_root(bt);

	char ch;
	btree_get_item(bt, root, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[0], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(NULL, btree_get_parent(bt, root));
	#endif
	
	tlink left, right;
	left = btree_get_lchild(bt, root);
	btree_get_item(bt, left, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[1], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(root, btree_get_parent(bt, left));
	#endif
	
	right = btree_get_rchild(bt, root);
	btree_get_item(bt, right, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[12], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(root, btree_get_parent(bt, right));
	#endif
	
	root = right;
	tlink tmp = btree_get_lchild(bt, root);
	btree_get_item(bt, tmp, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[13], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(root, btree_get_parent(bt, tmp));
	#endif
	
	tmp = btree_get_rchild(bt, root);
	btree_get_item(bt, tmp, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[16], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(root, btree_get_parent(bt, tmp));
	#endif
	
	root = left;
	left = btree_get_lchild(bt, root);
	btree_get_item(bt, left, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[2], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(root, btree_get_parent(bt, left));
	#endif
	
	right = btree_get_rchild(bt, root);
	btree_get_item(bt, right, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[9], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(root, btree_get_parent(bt, right));
	#endif
	
	root = left;
	left = btree_get_lchild(bt, root);
	btree_get_item(bt, left, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[3], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(root, btree_get_parent(bt, left));
	#endif
	
	right = btree_get_rchild(bt, root);
	btree_get_item(bt, right, &ch);
	CU_ASSERT_PTR_DATA_EQUAL(&ch, &str[6], sizeof(ch));
	#if BTREE_HAVE_PARENT
	CU_ASSERT_EQUAL(root, btree_get_parent(bt, right));
	#endif
	
	btree_close(bt);
}

/*
递归版遍历函数测试
*/
static void btree_order_test1(void)
{
/*
树:
	   +
	  / \
	 *   E
	/ \
     *   D
    / \
   /    C
  / \
A   B
*/
	char str[] = { '+', '*', '*', '/', 'A', '\0', '\0', 'B', '\0', '\0',
		'C', '\0', '\0', 'D', '\0', '\0', 'E', '\0', '\0' };
	char end_item = '\0';

	char str_rlt[sizeof(str) / sizeof(str[0])];

	btree bt = btree_open(sizeof(char));
	btree_make_btree(bt, str, &end_item);

	int index = 0;

	index = btree_preorder_recursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("+**/ABCDE", str_rlt, strlen("+**/ABCDE"));

	index = btree_inorder_recursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("A/B*C*D+E", str_rlt, strlen("A/B*C*D+E"));

	index = btree_postorder_recursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("AB/C*D*E+", str_rlt, strlen("AB/C*D*E+"));

	btree_close(bt);
}

/*
非递归版遍历函数测试
*/
static void btree_order_test2(void)
{
	/*
	树:
	+
	/ \
	*   E
	/ \
	*   D
	/ \
	/    C
	/ \
	A   B
	*/
	char str[] = { '+', '*', '*', '/', 'A', '\0', '\0', 'B', '\0', '\0',
		'C', '\0', '\0', 'D', '\0', '\0', 'E', '\0', '\0' };
	char end_item = '\0';

	char str_rlt[sizeof(str) / sizeof(str[0])];


	btree bt = btree_open(sizeof(char));
	btree_make_btree(bt, str, &end_item);

	int index = 0;

	index = btree_preorder_norecursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("+**/ABCDE", str_rlt, strlen("+**/ABCDE"));

	index = btree_preorder_norecursion2(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("+**/ABCDE", str_rlt, strlen("+**/ABCDE"));

	index = btree_inorder_norecursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("A/B*C*D+E", str_rlt, strlen("A/B*C*D+E"));

	index = btree_postorder_norecursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("AB/C*D*E+", str_rlt, strlen("AB/C*D*E+"));

	index = btree_postorder_norecursion2(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("AB/C*D*E+", str_rlt, strlen("AB/C*D*E+"));

	index = btree_levelorder(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("+*E*D/CAB", str_rlt, strlen("+*E*D/CAB"));

	index = btree_levelorderR(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("+E*D*C/BA", str_rlt, strlen("+E*D*C/BA"));

	btree_close(bt);
}

/*
非递归版遍历函数测试
*/
static void btree_order_test3(void)
{
	/*
	树:
	A
	/   \
	B      C
	/ \    / \
	D   E  F   G
	/ \
	H   I
	*/
	char str[] = { 'A', 'B', 'D', 'H', '\0', '\0', 'I', '\0', '\0', 'E',
		'\0', '\0', 'C', 'F', '\0', '\0', 'G', '\0', '\0' };

	char str_rlt[sizeof(str) / sizeof(str[0])];

	char end_item = '\0';

	btree bt = btree_open(sizeof(char));
	btree_make_btree(bt, str, &end_item);

	int index = 0;

	index = btree_preorder_norecursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("ABDHIECFG", str_rlt, strlen("ABDHIECFG"));

	index = btree_preorder_norecursion2(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("ABDHIECFG", str_rlt, strlen("ABDHIECFG"));

	index = btree_inorder_norecursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("HDIBEAFCG", str_rlt, strlen("HDIBEAFCG"));

	index = btree_postorder_norecursion(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("HIDEBFGCA", str_rlt, strlen("HIDEBFGCA"));

	index = btree_postorder_norecursion2(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("HIDEBFGCA", str_rlt, strlen("HIDEBFGCA"));

	index = btree_levelorder(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("ABCDEFGHI", str_rlt, strlen("ABCDEFGHI"));

	index = btree_levelorderR(bt, str_rlt);
	CU_ASSERT_EQUAL(index, 9);
	CU_ASSERT_PTR_DATA_EQUAL("ACBGFEDIH", str_rlt, strlen("ACBGFEDIH"));

	btree_close(bt);
}


/***********************************************************************************
***********************************************************************************/
CU_TestInfo tests_datasture_charpter05[] = {
	{ "create_btree_test", create_btree_test },
	{ "btree_order_test1", btree_order_test1 },
	{ "btree_order_test2", btree_order_test2 },
	{ "btree_order_test3", btree_order_test3 },
	CU_TEST_INFO_NULL,
};




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值