普通树(有根树)C++
对于普通树实现的细节包括
1 树结点的结构体
2 初始化及删除树结点(关注内存泄露)
3 递归先序遍历
4 通过关键值的查询操作,返回关键值的结点
5 凹入表实现
6 广义表实现
7 非递归先序遍历,利用栈作为辅助的数据结构
#include <iostream>
#include <crtdbg.h>
#include <cstring>
#include <assert.h>
using namespace std; typedef int DataType;
struct TreeNode
{
TreeNode()
{
sibling = NULL;
child = NULL;
}
DataType data;
TreeNode * sibling; //右兄弟结点
TreeNode * child; //左子结点
};
typedef TreeNode *DataStack; // 存储类型为 TreeNode*
//普通树
class Tree
{
private:
TreeNode *root;
Tree(const Tree &) {}//防止拷贝构造 与 赋值
Tree & operator=(const Tree &) { return *this; }
public:
Tree(const DataType &data);
~Tree();
const TreeNode * GetRoot()const { return root;}
TreeNode * GetRoot() { return root;}
void Init(const DataType &data);
void Destroy(TreeNode * p);//删除根结点
void DestroySub(TreeNode * p);//删除子结点;
TreeNode * InsertChild(TreeNode *p, DataType data);
TreeNode * InsertSibling(TreeNode *p, DataType data);
void Print(const TreeNode * p); //先序遍历
TreeNode * Find(TreeNode * p, DataType data);//寻找data返回并返回结点
void Print2(); //非递归先序遍历
};
//辅助类栈
class Stack
{
private:
struct Node
{
DataStack data;
Node *next;
};
Node * head;
void Init()
{
head = NULL;
}
void Destroy()
{
for (Node* p = head; p != NULL;)
{
Node *pTemp = p->next;
delete p ;
p = pTemp;
}
head = NULL;
}
public:
Stack()
{
Init();
}
~Stack()
{
Destroy();
}
void Push(DataStack data)
{
Node *p = new Node;
p->data = data;
p->next = head;
head = p;
}
DataStack Pop()
{
if (head == NULL)
{
return NULL;
}
Node *p = head;
DataStack temp = p->data;
head = head->next;
delete p;
p = NULL;
return temp;
}
int Getlenth()
{
int n = ;
for (Node *p = head; p != NULL; p = p->next)
{
++n;
}
return n;
}
DataStack Getop()
{
if (head == NULL)
{
return NULL;
}
return head->data;
}
bool Empty()
{
return (head == NULL);
}
};
//普通树方法实现
Tree::Tree(const DataType &data)
{
Init(data);
}
Tree::~Tree ()
{
Destroy(root);
}
void Tree::Init(const DataType &data)
{
root = new TreeNode;
root->child = NULL;
root->sibling = NULL;
root->data = data;
}
void Tree::Destroy(TreeNode * p)
{
if (p == NULL)
{
return;
}
Destroy(p->sibling);
Destroy(p->child);
delete p;
p = NULL;
}
void Tree::DestroySub(TreeNode * p)
{
if (p->child)
{
Destroy(p->child);
p->child = NULL;
}
}
TreeNode * Tree::InsertChild(TreeNode * p, DataType data)
{
if (p->child)
{
return p->child; //已有子结点
}
TreeNode *pNew = new TreeNode;
pNew->data = data;
p->child = pNew;
return pNew;
}
TreeNode * Tree::InsertSibling(TreeNode * p, DataType data)
{
if (p->sibling)
{
return p->sibling;//已有兄弟结点
}
TreeNode *pNew = new TreeNode;
pNew->data = data;
p->sibling = pNew;
return pNew;
}
//先序遍历
void Tree::Print(const TreeNode * p)
{
if(p==NULL)
{
return;
}
cout << p->data << endl;
Print(p->child);
Print(p->sibling);
}
//寻找data并返回结点
TreeNode * Tree::Find(TreeNode * p, DataType data)
{
if(p == NULL)
return NULL;
if (p->data == data)
{
return p;
}
TreeNode *pFind = Find(p->child, data);
if (pFind != NULL)
{
return pFind;
} return Find(p->sibling, data);
}
//非递归先序遍历
void Tree::Print2()
{
TreeNode *p = GetRoot();
if (p == NULL)
{
return;
}
Stack stack; while( (p != NULL) || (!stack.Empty()) )
{
if (p != NULL)
{
cout << p->data << endl;
stack.Push(p);
p = p->child;
}
else
{
p = stack.Pop();
p = p->sibling;
}
}
}
void AoRuBiao(const TreeNode *p, int depth)
{
if (p == NULL)
{
return;
}
for (int i=; i<depth; ++i)
{
cout << " ";
}
cout << p->data;
for (int i=; i<-depth; ++i)
{
cout << " - ";
}
cout << endl;
AoRuBiao(p->child, depth+);
AoRuBiao(p->sibling, depth);
}
void GuangYiBiao(const TreeNode *p)
{
if (p == NULL)
{
return;
}
cout << p->data;
if (p->child)
{
cout << "(";
}
GuangYiBiao(p->child);
if (p->child)
{
cout << ")";
}
if (p->sibling)
{
cout << ",";
}
GuangYiBiao(p->sibling);
} void main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); Tree tree(); //Stack s;
//s.Push(tree.GetRoot());
//cout << s.Getop()->data; TreeNode * p11 = tree.InsertChild(tree.GetRoot(), );
TreeNode * p12 = tree.InsertSibling(p11,);
TreeNode * p13 = tree.InsertSibling(p12,); TreeNode * p111 = tree.InsertChild(p11, );
TreeNode * p112 = tree.InsertSibling(p111,); TreeNode * p121 = tree.InsertChild(p12, );
TreeNode * p122 = tree.InsertSibling(p121,); tree.Print(tree.GetRoot());
//tree.DestroySub(p12);
//tree.Print(tree.GetRoot());
cout << "\n\nSearch p12" << endl;
TreeNode * temp = tree.Find(tree.GetRoot(),);
if (temp != NULL)
{
cout << temp->child->data <<endl;
cout << temp->sibling->data << endl;
} cout << "\n\nAoRuBiao " << endl;
AoRuBiao(tree.GetRoot(),); cout << "\nGuangYiBiao" << endl;
GuangYiBiao(tree.GetRoot()); cout << "\n\n非递归遍历" << endl;
tree.Print2(); system("pause");
}
(转载请注明作者和出处^_* Seven++ http://www.cnblogs.com/sevenPP/ )
普通树(有根树)C++的更多相关文章
- bzoj 4765: 普通计算姬 主席树+替罪羊树思想
题目大意: 给定一棵\(n\)个节点的带权树有根树,设\(sum_p\)表示以点\(p\)为根的这棵子树中所有节点的权 计算姬支持下列两种操作: 给定两个整数\(u,v\),修改点\(u\)的权值为\ ...
- 再谈树---无根树转有根树( dfs搜索转化+fa数组记录父节点) *【模板】
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <vector> ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ4551——[Tjoi2016&Heoi2016]树
1.题意: 给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个 结点,可以打多次标记.)2. 询问操作:询问某个 ...
- HDU 4605 Magic Ball Game (dfs+离线树状数组)
题意:给你一颗有根树,它的孩子要么只有两个,要么没有,且每个点都有一个权值w. 接着给你一个权值为x的球,它从更节点开始向下掉,有三种情况 x=w[now]:停在此点 x<w[now]:当有孩子 ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- HYSBZ 4551 (树状数组) 采花
题目:这里 题意: 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下 两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记, ...
- BZOJ 4551: [Tjoi2016&Heoi2016]树
4551: [Tjoi2016&Heoi2016]树 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 748 Solved: 394[Subm ...
- [bzoj4551][Tjoi2016][Heoi2016]树
Description 在2016年,佳媛姐姐刚刚学习了树,非常开心. 现在她想解决这样一个问题:给定一颗有根树(根为1),有以下两种操作: 1. 标记操作:对某个结点打上标记(在最开始,只有结点1有 ...
随机推荐
- iOS开发——UI篇&下拉弹出列表选择项效果
下拉弹出列表选择项效果 右边菜单中的按键,点击弹出一个列表可选择,选择其中一个,响应相应的事件并把文字显示在右边的菜单上:弹出下拉效果使用LMDropdownView插件,可以用POD进行加载pod ...
- dup和dup2函数
下面两个函数都可用来复制一个现存的文件描述符: #include<unistd.h> int dup(int filedes); int dup2(int filedes,int file ...
- OpenVPN莫名其妙断线的问题及其解决-confirm
本文很短,目的在于confirm一下凌乱的< OpenVPN莫名其妙断线的问题及其解决>,如果看觉得我比较啰嗦,那么一定要看看最后一个小节,好在CSDN为每篇文章都自动添加了目录,可以直接 ...
- Linux vi编辑器
vim在内存缓冲区中处理数据 如果在启动vim时未指定文件名,或者这个文件不存在,vim会新开一段缓冲区来编辑. h 左移一个字符 j 下移一行 k 上移一行 l 右边移一个字符 PageDown(C ...
- E - 最短的名字
Description 在一个奇怪的村子中,很多人的名字都很长,比如aaaaa, bbb and abababab. 名字这么长,叫全名显然起来很不方便.所以村民之间一般只叫名字的前缀.比如叫'aaa ...
- Uva120 Stacks of Flapjacks 翻煎饼
水水题.给出煎饼数列, 一次只能让第一个到第i个数列全部反转,要求把数列排序为升序. 算法点破后不值几钱... 只要想办法把最大的煎饼放到最后一个,然后就变成前面那些煎饼的数列的子题目了.递归或循环即 ...
- android源码编译过程
1.下载好android源码包. 2.装好vm,ubuntu(如果能在实体机装linux更好). 3.安装所需要的deb包 在终端执行如下命令: sudo apt-get install flex b ...
- 临时2级页表的初始化过程 head_32.S 相关代码解释
page_pde_offset = (__PAGE_OFFSET >> 20); /* __PAGE_OFFSET是0xc0000000,page_pde_offset = 3072 = ...
- Linux 下安装配置nginx及常见问题解答
其实也不能完全算是原创吧!都是我配置nginx时所遇到的问题,查阅资料后总结起来.即是巩固一下nginx的配置,也是分享给新入Linux的童鞋们一些知识 好了,不多废话,进入主题吧! 为nginx添加 ...
- java调用.net asmx服务
有时候,在java下开发会调用一下.net下写的服务,看网上有各种方法,但总是不成功,总结下自己测试过能调用成功的方式: 1. 原始方式http-soap public static String p ...