树和二叉树
1.二叉树的表示
2.二叉树的遍历
3.二叉树的基本操作
1.二叉树的表示
- 结构设计
#define END '#'
typedef char ElemType;
typedef struct BtNode
{
struct BtNode* leftchild;
struct BtNode* rightchild;
ElemType data;
}BtNode,*BinaryTree;
2.二叉树的遍历
所谓树的遍历,就是按某种次序访问树中的结点,要求每个结点访问一次且仅访问一次。
递归遍历
void PreOrder(BtNode* p)//先序遍历
{
if (p != NULL)
{
printf("%c ", p->data);
PreOrder(p->leftchild);
PreOrder(p->rightchild);
}
}
void InOrder(BtNode* p)//中序遍历
{
if (p != NULL)
{
InOrder(p->leftchild);
printf("%c ", p->data);
InOrder(p->rightchild);
}
}
void PastOrder(BtNode* p)//后序遍历
{
if (p != NULL)
{
PastOrder(p->leftchild);
PastOrder(p->rightchild);
printf("%c ", p->data);
}
}
非递归遍历
//非递归的先序遍历
void NicePreOrder(BtNode* ptr)
{
if (ptr == NULL)
return;
stack<BtNode*> st;
st.push(ptr);
while (!st.empty())
{
ptr = st.top();
st.pop();
cout << ptr->data << " ";
if (ptr->rightchild != NULL)
{
st.push(ptr->rightchild);
}
if (ptr->leftchild != NULL)
{
st.push(ptr->leftchild);
}
}
cout << endl;
}
//非递归的中序遍历
void NiceInOrder(BtNode* ptr)
{
if (ptr == NULL)
{
return;
}
stack<BtNode*> st;
while (ptr != NULL || !st.empty())
{
while (ptr != NULL)
{
st.push(ptr);
ptr = ptr->leftchild;
}
ptr = st.top();
st.pop();
cout << ptr->data << " ";
ptr = ptr->rightchild;
}
cout << endl;
}
//非递归的后序遍历
//法一:
void NicePastOrder(BtNode* ptr)
{
if (ptr == NULL)
{
return;
}
stack<BtNode*> st;
BtNode* tag = NULL;
while (ptr != NULL || !st.empty())
{
while (ptr != NULL)
{
st.push(ptr);
ptr = ptr->leftchild;
}
ptr = st.top();
st.pop();
if (ptr->rightchild == NULL || ptr->rightchild == tag)
{
cout << ptr->data << " ";
tag = ptr;
ptr = NULL;
}
else
{
st.push(ptr);
ptr = ptr->rightchild;
}
}
cout << endl;
}
//法二:
struct StkNode
{
int popnum;
BtNode* pnode;
public:
StkNode(BtNode* p = NULL) : popnum(0),pnode(p){}
};
void StkNicePastOrder(BtNode* ptr)
{
if (ptr == NULL)
return;
stack<StkNode> st;
st.push(StkNode(ptr));
while (!st.empty())
{
StkNode node = st.top();
st.pop();
if (++node.popnum == 3)
{
cout << node.pnode->data << " ";
}
else
{
st.push(node);
if (node.popnum == 1 && node.pnode->leftchild != NULL)
{
st.push(StkNode(node.pnode->leftchild));
}
else if (node.popnum == 2 && node.pnode->rightchild != NULL)
{
st.push(StkNode(node.pnode->rightchild));
}
}
}
cout << endl;
}
创建二叉树
struct BtNode* Buynode()//创建一个结点
{
BtNode* s = (BtNode*)malloc(sizeof(*s));
if (NULL == s)
exit(EXIT_FAILURE);
memset(s, 0, sizeof(*s));
return s;
}
BtNode* CreateTree()
{
ElemType ch;
BtNode* s = NULL;
cin >> ch;
if (ch != END)
{
s = Buynode();
s->data = ch;
s->leftchild = CreateTree();
s->rightchild = CreateTree();
}
return s;
}
利用先序和中序创建二叉树
int FindIs(char* is, int n, char val)
{
int pos = -1;
for (int i = 0; i < n; i++)
{
if (is[i] == val)
{
pos = i;
break;
}
}
return pos;
}
BtNode* CreatePI(char* ps, char* is, int n)
{
BtNode* s = NULL;
if (n > 0)
{
s = Buynode();
s->data = ps[0];
int pos = FindIs(is, n, ps[0]);
if (pos == -1)
{
exit(EXIT_FAILURE);
}
s->leftchild = CreatePI(ps + 1, is, pos);
s->rightchild = CreatePI(ps + 1 + pos, is + 1 + pos, n - pos - 1);
}
return s;
}
BtNode* CreateTreePI(char* ps, char* is, int n)//利用先序和中序创建二叉树
{
BtNode* s = NULL;
if (ps != NULL && is != NULL && n > 0)
{
s = CreatePI(ps, is, n);
}
return s;
}
利用中序和后序创建二叉树
int FindIs(char* is, int n, char val)
{
int pos = -1;
for (int i = 0; i < n; i++)
{
if (is[i] == val)
{
pos = i;
break;
}
}
return pos;
}
BtNode* CreateIL(char* is, char* ls, int n)
{
BtNode* s = NULL;
if (n > 0)
{
s = Buynode();
s->data = ls[n - 1];
int pos = FindIs(is, n, ls[n - 1]);
if (pos == -1)
exit(EXIT_FAILURE);
s->leftchild = CreateIL(is, ls, pos);
s->rightchild = CreateIL(is + pos + 1, ls + pos, n - pos - 1);
}
return s;
}
BtNode* CreateTreeIL(char* is, char* ls, int n)//利用中序和后序创建二叉树
{
BtNode* root = NULL;
if (is != NULL && ls != NULL && n > 0)
{
root = CreateIL(is, ls, n);
}
return root;
}
遍历字符串
1.层次遍历 == 心跳打印
/利用一个队列进行操作/
void NiceLevelOrder(BtNode* ptr)
{
if(ptr == NULL)
{
return ;
}
queue<BtNode*> qu;
qu.push(ptr);
while(!qu.empty())
{
ptr = qu.front();//取队头元素
qu.pop();//删除队头元素
cout<<ptr->data<<" ";
if(ptr->leftchild != NULL)
{
qu.push(ptr->leftchild);
}
if(ptr->rightchild != NULL)
{
qu.push(ptr->rightchild);
}
cout<<endl;
}
}
2.“Z字形遍历”
/利用两个栈来进行操作/
void ZNiceLevelOrder(BtNode* ptr)
{
if(ptr == NULL)
{
return ;
}
stack<BtNode*> lst;
stack<BtNode*> rst;
lst.push(ptr);
while(!lst.empty() || !rst.empty())
{
while(!lst.empty())
{
ptr = lst.top();
lst.pop();
cout<<ptr->data<<" ";
if(ptr->leftchild != NULL)
{
rst.push(ptr->leftchild);
}
if(ptr->rightchild != NULL)
{
rst.push(ptr->rightchild);
}
}
while(!rst.empty())
{
ptr = rst.top();
rst.pop();
cout<<ptr->data<<" ";
if(ptr->rightchild != NULL)
{
lst.push(ptr->rightchild);
}
if(ptr->leftchild != NULL)
{
lst.push(ptr->leftchild);
}
}
}
cout<<endl;
}
计算二叉树结点的个数
int GetSize(BtNode* ptr)
{
if(ptr == NULL)
{
return 0;
}
else
{
return GetSize(ptr->leftchild) + GetSize(ptr->rightchild) + 1;
}
}
计算二叉树的深度
int Get_Depth(BtNode* ptr)
{
if(ptr == NULL)
{
return 0;
}
else
{
return std::max(Get_Depth(ptr->leftchild),Get_Depth(ptr->rightchild)) + 1;
}
}
寻找某结点的值
法一:利用先序遍历进行寻找(比较)
BtNode* Findvalue(BtNode* ptr,ElemType val)
{
if(root == NULL)
{
return NULL;
}
stack<BtNode*> st;
st.push(ptr);
while(!st.empty())
{
ptr = st.top();
st.pop();
if(ptr->data == val)
{
return ptr;
}
if(ptr->leftchild != NULL)
{
st.push(ptr->leftchild);
}
if(ptr->rightchild != NULL)
{
st.push(ptr->rightchild);
}
}
return NULL;
}
//法二:
BtNode* FindValue(BtNode* ptr,ElemType val)
{
if(ptr == NULL || ptr->data == val)
{
return ptr;
}
else
{
BtNode* p = FindValue(ptr->leftchild,val);
if(nullptr == p)
{
p = FindValue(ptr->rightchild,val);
}
return p;
}
}
判断是否为满二叉树
//法一:
bool Is_Full(BtNode* ptr)
{
return (ptr == NULL) && Is_Full(ptr->leftchild) && Is_Full(ptr->rightchild) && Get_Depth(ptr->leftchild) == Get_Depth(ptr->rightchild);
}
//法二:
bool Is_Full_BinaryTree(BtNode* ptr)
{
bool res = true;
if(ptr == NULL)
{
return res;
}
queue<BtNode*> qu1,qu2;
int n = 1;
qu1.push(ptr);
while(!qu1.empty() || !qu2.empty())
{
if(n != qu1.size())
{
res = false;
break;
}
while(!qu1.empty())
{
BtNode* p = qu1.front();
qu1.pop();
if(p->leftchild != NULL)
{
qu2.push(p->leftchild);
}
if(p->rightchild != NULL)
{
qu2.push(p->rightchild);
}
n += n;
if(n != qu2.size())
{
res = false;
break;
}
while(!qu2.empty())
{
BtNode* p = qu2.front();
qu2.pop();
if(p->leftchild != NULL)
{
qu1.push(p->leftchild);
}
if(p->rightchild != NULL)
{
qu1.push(p->rightchild);
}
}
n += n;
}
return res;
}
判断是否为完全二叉树
bool Is_Comp_BonaryTree(BtNode* ptr)
{
bool res = true;
if(ptr == nullptr)
{
return res;
}
queue<BtNode*> qu;
qu.push(ptr);
while(!qu.empty())
{
BtNode* p = qu.front();
qu.pop();
if(p == NULL)
{
break;
}
qu.push(p->leftchild);
qu.push(p->rightchild);
}
while(!qu.empty())
{
BtNode* p = qu.front();
qu.pop();
if(p != NULL)
{
res = false;
break;
}
}
return res;
}
求最大路径和并输出路径
void PrintPath(BtNode* ptr,int val,vector<int>& vec)
{
if(ptr == NULL)
{
return;
}
vec.push_back(ptr->data);
if(ptr->leftchild == NULL && ptr->rightchild == NULL)
{
int sum = 0;
for(int i = 0; i < vec.size(); i++)
{
sum += vec[i];
}
if(sum == val)
{
for(int i = 0; i < vec.size(); i++)
{
cout<<vec[i]<<" ";
}
cout<<endl;
}
}
PrintPath(ptr->leftchild,val,vec);
PrintPath(ptr->rightchild,val,vec);
vec.pop_back();
}
将二叉搜索树变为二叉链表
//法一:利用非递归的中序遍历改成链式的过程
void CNiceInOrder(BtNode* ptr)
{
if(ptr == NULL)
{
return ;
}
stack<BtNode*> st;
BtNode* head = NULL:
BtNode* nt = NULL;
while(!st.empty() || ptr != NULL)
{
while(ptr != NULL)
{
st.push(ptr);
ptr = ptr->leftchild;
}
ptr = st.top();
st.pop();
if(head == NULL)
{
head = ptr;
nt = ptr;
}
else
{
nt->rightchild = ptr;
ptr->leftchild = nt;
nt = ptr;
}
ptr = ptr->rightchild;
}
cout<<endl;
}
//法二:利用递归的中序遍历改为链式
void InList(BtNode* ptr,BtNode*& pre,BtNode*& head)
{
if(ptr != NULL)
{
InList(ptr->leftchild,pre);
if(pre != NULL)
{
pre->rightchild = ptr;
ptr->leftchild = pre;
}
else
{
head = ptr;
}
pre = ptr;
InList(ptr->rightchild,pre,head);
}
}
BtNode* InOrder_Lt(BtNode* ptr)
{
if(ptr != NULL)
{
return NULL;
}
BtNode* pre = NULL;
BtNode* head = NULL;
InList(ptr,pre,head);
return head;
}
//将二叉搜索树变成倒过来的链式存储
BtNode* RCNiceInOrder(BtNode* ptr)
{
if(ptr == NULL)
{
return NULL;
}
stack<BtNode*> st;
BtNode* head = NULL;
BtNode* nt = NULL;
while(!st.empty() || ptr != NULL)
{
while(ptr != NULL)
{
st.push(ptr);
ptr = ptr->leftchild;
}
ptr = st.top();
st.pop();
if(head == NULL)
{
head = ptr;
}
else
{
nt = ptr->rightchild;
head->leftchild = ptr;
ptr->rightchild = head;
head = ptr;
}
ptr = nt;
}
return head;
}