// Tree.h: interface for the CTree class.
//
//
#if !defined(AFX_TREE_H__35796AC2_439A_4B70_943C_D75B3D70417F__INCLUDED_)
#define AFX_TREE_H__35796AC2_439A_4B70_943C_D75B3D70417F__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
typedef struct tree_node_ {
public:
tree_node_ *parent;
tree_node_ *first_child, *last_child;
tree_node_ *prev_sibling, *next_sibling;
int data;
}TreeNode,*PTREENODE;
class CTree
{
public:
CTree();
CTree(int i);
virtual ~CTree();
public:
void Init();
void Free();
void FreeOne(PTREENODE ptreeNode);
PTREENODE Search(int i); // 查找数据域为值i的节点
// 查找当前节点或当前节点右兄弟的最左孩子(即下层开始节点),若都不存在最左孩子,则返回空
PTREENODE FindFirstChild(const PTREENODE treeNodeFather);
// 恢复节点所在层的初始连接属性。pptreeNode为该层首节点
void RecoverTreeNode(PTREENODE *pptreeNode);
// 判断两节点是否为左右兄弟关系
BOOL IsInNextSiblingOrder(PTREENODE pFirstTreeNode, PTREENODE pSecondTreeNode);
public:
static PTREENODE BuildTreeNode(TreeNode *parent,TreeNode *first_child,TreeNode *last_child,
TreeNode *prev_sibling, TreeNode *next_sibling, int data);
private:
PTREENODE m_ptree; // 存储树
PTREENODE m_ptreeNodeFather; // 层次遍历时当前层的开始节点
PTREENODE m_ptreeNodeFirstChild; // 层次遍历时下一层的开始节点
};
#endif // !defined(AFX_TREE_H__35796AC2_439A_4B70_943C_D75B3D70417F__INCLUDED_)
// Tree.cpp: implementation of the CTree class.
//
//
#include "stdafx.h"
#include "TreeSearch.h"
#include "Tree.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
void FreeTreeNode(void *lpvoid)
{
if(lpvoid)
{
free(lpvoid);
}
lpvoid = NULL;
}
CTree::CTree()
{
// m_ptree = (PTREENODE)malloc(sizeof(TreeNode));
// m_ptreeNodeFather = (PTREENODE)malloc(sizeof(TreeNode));
// m_ptreeNodeFirstChild = (PTREENODE)malloc(sizeof(TreeNode));
m_ptree = NULL;
m_ptreeNodeFather = NULL;
m_ptreeNodeFirstChild = NULL;
}
CTree::CTree(int i)
{
// m_ptree = (PTREENODE)malloc(sizeof(TreeNode));
// m_ptreeNodeFather = (PTREENODE)malloc(sizeof(TreeNode));
// m_ptreeNodeFirstChild = (PTREENODE)malloc(sizeof(TreeNode));
m_ptree = BuildTreeNode(NULL,NULL,NULL,NULL,NULL,i);
m_ptreeNodeFather = m_ptree;
m_ptreeNodeFirstChild = FindFirstChild(m_ptreeNodeFather);
}
CTree::~CTree()
{
// free(m_ptreeNodeFather);
// free(m_ptreeNodeFirstChild);
Free();
}
void CTree::Init()
{
// 构造如下树
// 0
// / /
// 1 2
// / / / /
// 3 4 5 6
// | / /
// 7 8 9
// / /
// 10 11
PTREENODE ptreeNodeFirstChild = BuildTreeNode(m_ptree,NULL,NULL,NULL,NULL,1);
m_ptree->first_child = ptreeNodeFirstChild;
PTREENODE ptreeNodeLastChild = BuildTreeNode(m_ptree,NULL,NULL,ptreeNodeFirstChild,NULL,2);
m_ptree->last_child = ptreeNodeLastChild;
ptreeNodeFirstChild->next_sibling = ptreeNodeLastChild;
PTREENODE ptreeNodeGrandChild = BuildTreeNode(ptreeNodeFirstChild,NULL,NULL,NULL,NULL,3);
ptreeNodeFirstChild->first_child = ptreeNodeGrandChild;
PTREENODE ptreeNodeGrandChild2 = BuildTreeNode(ptreeNodeFirstChild,NULL,NULL,ptreeNodeGrandChild,NULL,4);
ptreeNodeFirstChild->last_child = ptreeNodeGrandChild2;
ptreeNodeGrandChild->next_sibling = ptreeNodeGrandChild2;
PTREENODE ptreeNodeGrandChild3 = BuildTreeNode(ptreeNodeLastChild,NULL,NULL,NULL,NULL,5);
ptreeNodeLastChild->first_child = ptreeNodeGrandChild3;
PTREENODE ptreeNodeGrandChild4 = BuildTreeNode(ptreeNodeLastChild,NULL,NULL,ptreeNodeGrandChild3,NULL,6);
ptreeNodeLastChild->last_child = ptreeNodeGrandChild4;
ptreeNodeGrandChild3->next_sibling = ptreeNodeGrandChild4;
PTREENODE ptreeNodeGrandChild7 = BuildTreeNode(ptreeNodeGrandChild2,NULL,NULL,NULL,NULL,7);
ptreeNodeGrandChild2->first_child = ptreeNodeGrandChild7;
ptreeNodeGrandChild2->last_child = ptreeNodeGrandChild7;
PTREENODE ptreeNodeGrandChild5 = BuildTreeNode(ptreeNodeGrandChild4,NULL,NULL,NULL,NULL,8);
ptreeNodeGrandChild4->first_child = ptreeNodeGrandChild5;
PTREENODE ptreeNodeGrandChild6 = BuildTreeNode(ptreeNodeGrandChild4,NULL,NULL,ptreeNodeGrandChild5,NULL,9);
ptreeNodeGrandChild4->last_child = ptreeNodeGrandChild6;
ptreeNodeGrandChild5->next_sibling = ptreeNodeGrandChild6;
PTREENODE ptreeNodeGrandChild8 = BuildTreeNode(ptreeNodeGrandChild7,NULL,NULL,NULL,NULL,10);
ptreeNodeGrandChild7->first_child = ptreeNodeGrandChild8;
PTREENODE ptreeNodeGrandChild9 = BuildTreeNode(ptreeNodeGrandChild7,NULL,NULL,ptreeNodeGrandChild8,NULL,11);
ptreeNodeGrandChild7->last_child = ptreeNodeGrandChild9;
ptreeNodeGrandChild8->next_sibling = ptreeNodeGrandChild9;
m_ptreeNodeFather = m_ptree;
m_ptreeNodeFirstChild= FindFirstChild(m_ptreeNodeFather);
}
PTREENODE CTree::Search( int i )
{
PTREENODE pTarget = NULL; //用于存储目标树节点
PTREENODE ptreeNode = NULL; //循环控制变量
// 指向下层首节点的最右相连兄弟(即同一父节点的最右孩子)
// 用于使其与父节点的兄弟节点下的下一最左孩子单向右连通(当遍历孩子那层节点完后进行还原)
// 比如使下边树节点2 的最右孩子5 的右兄弟(本为空)指向6,
// (还原条件:当下层扫描进行完5后,判断5->next_sibling->prev_sibling 是否为本身,否则把5->next_sibling置空)
// 1
// / /
// 2 3
// / / / /
// 4 5 6 7
PTREENODE ptreeNodeChild = NULL;
//以m_ptreeNodeFather为根节点循环遍历每层
do
{
ptreeNode = m_ptreeNodeFather;
// 若下层首节点非空,则把其指向下层首节点的最右相连兄弟
// 由于每次获取前,m_ptreeNodeFather所在层必定已经
// ptreeNodeChild = FindFirstChild(m_ptreeNodeFather);
// if (NULL != ptreeNodeChild)
// {
// ptreeNodeChild = ptreeNodeChild->parent->last_child;
// }
ptreeNodeChild = NULL;
if (NULL != m_ptreeNodeFirstChild)
{
ptreeNodeChild = m_ptreeNodeFirstChild->parent->last_child;
}
// 循环遍历当前层
while (NULL != ptreeNode)
{
if (ptreeNode->data == 1000)
{
pTarget = ptreeNode;
break;
}
printf("%d ", ptreeNode->data);
char a[10];
itoa(ptreeNode->data,a,10);
CString s;
s.Format(_T("%s"),a);
OutputDebugString(s);
ptreeNode = ptreeNode->next_sibling;
if (NULL != ptreeNode && NULL != ptreeNode->first_child) //若节点存在孩子,则使其孩子节点左边相邻节点(未连通,如上图节点5)右向单连通
{
// 下边if语句为避免以下情况发生:ptreeNodeChild = 7,此时ptreeNode=3,错误地将7->next_sibling指向6
// 1
// / /
// 2 3
// / /
// 6 7
if (IsInNextSiblingOrder(ptreeNodeChild->parent,ptreeNode))
{
//由上边if语句条件成立可知ptreeNodeChild必定非空。
ptreeNodeChild->next_sibling = ptreeNode->first_child; // 置节点右向单连通
ptreeNodeChild = ptreeNodeChild->parent->last_child; // 更新值
}
}
}
// 找到该节点,则返回
if (NULL != pTarget)
{
RecoverTreeNode(&m_ptreeNodeFather); // 还原当前遍历层
RecoverTreeNode(&m_ptreeNodeFirstChild); // 还原子节点层
break;
}
RecoverTreeNode(&m_ptreeNodeFather); // 还原当前遍历层
m_ptreeNodeFather = m_ptreeNodeFirstChild; // 把当前层首节点指向下层首节点
m_ptreeNodeFirstChild = FindFirstChild(m_ptreeNodeFather);
}while (NULL != m_ptreeNodeFather);
m_ptreeNodeFather = m_ptree;
m_ptreeNodeFirstChild = FindFirstChild(m_ptreeNodeFather);
return pTarget;
}
PTREENODE CTree::FindFirstChild( const PTREENODE treeNodeFather )
{
PTREENODE ptreeNodeFirstChild = treeNodeFather;
if (NULL != ptreeNodeFirstChild) // 节点本身为空的情况下返回NULL
{
while ((NULL == ptreeNodeFirstChild->first_child) && (NULL != ptreeNodeFirstChild->next_sibling))
{
ptreeNodeFirstChild = ptreeNodeFirstChild->next_sibling;
}
return ptreeNodeFirstChild->first_child;
}
else
return NULL;
}
PTREENODE CTree::BuildTreeNode( TreeNode *parent,TreeNode *first_child,TreeNode *last_child,
TreeNode *prev_sibling, TreeNode *next_sibling, int data )
{
PTREENODE ptreeNode = (PTREENODE)malloc(sizeof(TreeNode));
// ptreeNode->parent = (PTREENODE)malloc(sizeof(TreeNode));
ptreeNode->parent = parent;
// ptreeNode->first_child = (PTREENODE)malloc(sizeof(TreeNode));
ptreeNode->first_child = first_child;
// ptreeNode->last_child = (PTREENODE)malloc(sizeof(TreeNode));
ptreeNode->last_child = last_child;
// ptreeNode->next_sibling = (PTREENODE)malloc(sizeof(TreeNode));
ptreeNode->next_sibling = next_sibling;
// ptreeNode->prev_sibling = (PTREENODE)malloc(sizeof(TreeNode));
ptreeNode->prev_sibling = prev_sibling;
ptreeNode->data = data;
return ptreeNode;
}
// 若当前节点的下一兄弟节点的左兄弟节点不为当前节点(或者为空),则把当前节点的下一兄弟节点置空。
void CTree::RecoverTreeNode( PTREENODE *pptreeNode )
{
if (NULL != pptreeNode)
{
PTREENODE ptreeNode= *pptreeNode;
PTREENODE pTemp = NULL;
while (NULL != ptreeNode)
{
if (NULL != ptreeNode->next_sibling)
{
if (NULL == ptreeNode->next_sibling->prev_sibling) // or ptreeNode != ptreeNode->next_sibling->prev_sibling
{
pTemp = ptreeNode->next_sibling;
ptreeNode->next_sibling = NULL;
// ptreeNode = pTemp;
//break;
}
}
if (NULL != pTemp)
{
ptreeNode = pTemp;
pTemp = NULL;
}
else
{
ptreeNode = ptreeNode->next_sibling;
}
}
}
}
void CTree::Free()
{
PTREENODE pTarget = NULL; //用于存储目标树节点
PTREENODE ptreeNode = NULL; //循环控制变量
// 指向下层首节点的最右相连兄弟(即同一父节点的最右孩子)
// 用于使其与父节点的兄弟节点下的下一最左孩子单向右连通(当遍历孩子那层节点完后进行还原)
// 比如使下边树节点2 的最右孩子5 的右兄弟(本为空)指向6,
// (还原条件:当下层扫描进行完5后,判断5->next_sibling->prev_sibling 是否为本身,否则把5->next_sibling置空)
// 1
// / /
// 2 3
// / / / /
// 4 5 6 7
PTREENODE ptreeNodeChild = NULL;
//以m_ptreeNodeFather为根节点循环遍历每层
do
{
ptreeNode = m_ptreeNodeFather;
// 若下层首节点非空,则把其指向下层首节点的最右相连兄弟
// 由于每次获取前,m_ptreeNodeFather所在层必定已经
// ptreeNodeChild = FindFirstChild(m_ptreeNodeFather);
// if (NULL != ptreeNodeChild)
// {
// ptreeNodeChild = ptreeNodeChild->parent->last_child;
// }
ptreeNodeChild = NULL;
if (NULL != m_ptreeNodeFirstChild)
{
ptreeNodeChild = m_ptreeNodeFirstChild->parent->last_child;
}
// 循环遍历当前层
while (NULL != ptreeNode)
{
pTarget = ptreeNode;
printf("%d ", ptreeNode->data);
char a[10];
itoa(ptreeNode->data,a,10);
CString s;
s.Format(_T("%s"),a);
OutputDebugString(s);
ptreeNode = ptreeNode->next_sibling;
if (NULL != ptreeNode && NULL != ptreeNode->first_child) //若节点存在孩子,则使其孩子节点左边相邻节点(未连通,如上图节点5)右向单连通
{
// 下边if语句为避免以下情况发生:ptreeNodeChild = 7,此时ptreeNode=3,错误地将7->next_sibling指向6
// 1
// / /
// 2 3
// / /
// 6 7
if (IsInNextSiblingOrder(ptreeNodeChild->parent,ptreeNode))
{
//由上边if语句条件成立可知ptreeNodeChild必定非空。
ptreeNodeChild->next_sibling = ptreeNode->first_child; // 置节点右向单连通
ptreeNodeChild = ptreeNodeChild->parent->last_child; // 更新值
}
}
}
// // 找到该节点,则返回
// if (NULL != pTarget)
// {
// RecoverTreeNode(&m_ptreeNodeFather); // 还原当前遍历层
// RecoverTreeNode(&m_ptreeNodeFirstChild); // 还原子节点层
// break;
// }
//RecoverTreeNode(&m_ptreeNodeFather); // 还原当前遍历层
FreeOne(m_ptreeNodeFather);
m_ptreeNodeFather = m_ptreeNodeFirstChild; // 把当前层首节点指向下层首节点
m_ptreeNodeFirstChild = FindFirstChild(m_ptreeNodeFather);
}while (NULL != m_ptreeNodeFather);
m_ptreeNodeFather = m_ptree;
m_ptreeNodeFirstChild = FindFirstChild(m_ptreeNodeFather);
}
BOOL CTree::IsInNextSiblingOrder( PTREENODE pFirstTreeNode, PTREENODE pSecondTreeNode )
{
BOOL bResult = FALSE;
if (pFirstTreeNode && pSecondTreeNode)
{
PTREENODE pTemp = pFirstTreeNode;
while (NULL != pTemp)
{
pTemp = pTemp->next_sibling;
if (pTemp == pSecondTreeNode)
{
bResult = TRUE;
}
}
}
return bResult;
}
void CTree::FreeOne( PTREENODE ptreeNode )
{
if (NULL != ptreeNode)
{
PTREENODE pTemp = NULL;
while (NULL != ptreeNode)
{
pTemp = ptreeNode->next_sibling;
FreeTreeNode(ptreeNode);
ptreeNode = pTemp;
}
}
}