转至:http://www.cnblogs.com/charley_yang/archive/2010/12/08/1900256.html
关于二叉树可以参考wiki:http://zh.wikipedia.org/zh-cn/%E4%BA%8C%E5%8F%89%E6%A0%91
001 | /********************************************************* |
002 | * Description:参数传递:C++ 二叉树的实现以及指针使用注意事项 |
003 | * Author:charley |
004 | * DateTime:2010-12-8 11:00 |
005 | * Compile Environment:win7+vs2008 |
006 | ***********************************************************/ |
007 | |
008 | #include <iostream> |
009 | using namespace std; |
010 | |
011 | //************************************************************************************* |
012 | //二叉树结点类的定义 |
013 | template < class T> //模版结构体 |
014 | struct TreeNode |
015 | { |
016 | T data; //节点的内容 |
017 | TreeNode <T> *Lchild,*Rchild; //节点的左子树和右子树 |
018 | |
019 | //可选择参数的默认构造函数 |
020 | /*TreeNode(T nodeValue = T(),TreeNode<T> *leftNode = NULL,TreeNode<T> *rightNode = NULL ) |
021 | :data(nodeValue),Lchild(leftNode),Rchild(rightNode){} */ |
022 | }; |
023 | |
024 | //************************************************************************************** |
025 | //二叉树的建立 |
026 | template < class T> //模版方法 |
027 | void createBinaryTree(TreeNode<T> *&root ) //传递指针的引用 |
028 | { |
029 | TreeNode<T>* p = root; |
030 | T nodeValue ; |
031 | cin>>nodeValue; |
032 | if (nodeValue==-1) |
033 | { |
034 | root=NULL; |
035 | } |
036 | else |
037 | { |
038 | root= new TreeNode<T>(); //构造一个节点 |
039 | root->data = nodeValue; |
040 | createBinaryTree(root->Lchild); //递归构造左子树 |
041 | createBinaryTree(root->Rchild); //递归构造右子树 |
042 | } |
043 | } |
044 | |
045 | //************************************************************************************ |
046 | //二叉树的先序遍历 |
047 | template < class T> |
048 | void preOrder( TreeNode<T> * & p) //传递指针的引用 |
049 | { |
050 | if (p) |
051 | { |
052 | cout<<p->data<< " " ; |
053 | preOrder(p->Lchild); |
054 | preOrder(p->Rchild); |
055 | } |
056 | } |
057 | |
058 | //************************************************************************************** |
059 | //二叉树的中序遍历 |
060 | template < class T> |
061 | void inOrder(TreeNode<T> * & p) //传递指针的引用 |
062 | { |
063 | |
064 | if (p) |
065 | { |
066 | inOrder(p->Lchild); |
067 | cout<<p->data<< " " ; |
068 | inOrder(p->Rchild); |
069 | } |
070 | } |
071 | |
072 | //************************************************************************************** |
073 | //二叉树的后序遍历 |
074 | template < class T> |
075 | void postOrder(TreeNode<T> *& p) //传递指针的引用 |
076 | { |
077 | if (p) |
078 | { |
079 | postOrder(p->Lchild); |
080 | postOrder(p->Rchild); |
081 | cout<<p->data<< " " ; |
082 | } |
083 | } |
084 | |
085 | //************************************************************************************* |
086 | //统计二叉树中结点的个数 |
087 | template < class T> |
088 | int countNode(TreeNode<T> * & p) //传递指针的引用 |
089 | { |
090 | if (p == NULL) return 0; |
091 | return 1+countNode(p->Lchild)+countNode(p->Rchild); |
092 | } |
093 | |
094 | //*********************************************************************************** |
095 | //求二叉树的深度 |
096 | template < class T> |
097 | int depth(TreeNode<T> *& p) //传递指针的引用 |
098 | { |
099 | if (p == NULL) |
100 | return -1; |
101 | int h1 = depth(p->Lchild); |
102 | int h2 = depth(p->Rchild); |
103 | if (h1>h2) return (h1+1); |
104 | return h2+1; |
105 | } |
106 | |
107 | //*********************************************************************************** |
108 | //二叉树的消毁操作 |
109 | //容易混淆的错误声明:void destroy(TreeNode<T>* p) 这种声明会创建一个局部的临时对象来保存传递的指针 |
110 | //虽然2个指针都执行同一块堆空间,delete局部指针 也会删除二叉树结构所占用的堆内存 |
111 | //但是全局传递的那个指针将会是垃圾指针,会产生不可预料的错误 |
112 | //void destroy(TreeNode<T> *& p) 此函数的参数为全局指针的一个别名,代表全局指针rootNode本身 |
113 | // 这样p = NULL;能达到置空指针的左右 |
114 | //可选的方案是在调用完destroy方法之后,在主函数中执行rootNode = NULL操作 |
115 | template < class T> |
116 | void destroy(TreeNode<T> *& p) //传递指针的引用,消毁函数,用来消毁二叉树中的各个结点 |
117 | { |
118 | if (p) |
119 | { |
120 | //错误 return之后 没有执行delete p |
121 | //return destroy(p->Lchild); |
122 | //return destroy(p->Rchild); |
123 | |
124 | destroy(p->Lchild); |
125 | destroy(p->Rchild); |
126 | |
127 | //delete只能释放由用户通过new方式在堆中申请的内存, |
128 | //是通过变量声明的方式由系统所声明的栈内存不能使用delete删除 |
129 | |
130 | //delete和free函数一样,不修改它参数对应指针指向的内容,也不修改指针本身, |
131 | //只是在堆内存管理结构中将指针指向的内容标记为可被重新分配 |
132 | delete p; |
133 | |
134 | //堆上内存释放 栈上指针并不销毁 |
135 | //此时p指向的地址未知,此时执行*p = ? 操作会导致不可预料的错误 |
136 | //但是可以重新赋值p = &x; |
137 | //最好delete之后把P置空 |
138 | p = NULL; |
139 | |
140 | } |
141 | } |
142 | |
143 | //******************************************************************************** |
144 | //主函数的设计 |
145 | int main () |
146 | { |
147 | TreeNode< int > * rootNode = NULL; |
148 | int choiced = 0; |
149 | while ( true ) |
150 | { |
151 | system ( "cls" ); //清屏 |
152 | cout<< "\n\n\n ---主界面---\n\n\n" ; |
153 | cout<< " 1、创建二叉树 2、先序遍历二叉树\n" ; |
154 | cout<< " 3、中序遍历二叉树 4、后序遍历二叉树\n" ; |
155 | cout<< " 5、统计结点总数 6、查看树深度 \n" ; |
156 | cout<< " 7、消毁二叉树 0、退出\n\n" ; |
157 | cout<< " 请选择操作:" ; |
158 | cin>>choiced; |
159 | if (choiced == 0) |
160 | return 0; |
161 | else if (choiced == 1) |
162 | { |
163 | system ( "cls" ); |
164 | cout<< "请输入每个结点,回车确认,并以-1结束:\n" ; |
165 | createBinaryTree(rootNode ); |
166 | } |
167 | else if (choiced == 2) |
168 | { |
169 | system ( "cls" ); |
170 | cout<< "先序遍历二叉树结果:\n" ; |
171 | preOrder(rootNode); |
172 | cout<<endl; |
173 | system ( "pause" ); //暂停屏幕 |
174 | } |
175 | else if (choiced == 3) |
176 | { |
177 | system ( "cls" ); |
178 | cout<< "中序遍历二叉树结果:\n" ; |
179 | inOrder(rootNode); |
180 | cout<<endl; |
181 | system ( "pause" ); |
182 | } |
183 | else if (choiced == 4) |
184 | { |
185 | system ( "cls" ); |
186 | cout<< "后序遍历二叉树结果:\n" ; |
187 | postOrder(rootNode); |
188 | cout<<endl; |
189 | system ( "pause" ); |
190 | } |
191 | else if (choiced == 5) |
192 | { |
193 | system ( "cls" ); |
194 | int count = countNode(rootNode); |
195 | cout<< "二叉树中结点总数为" <<count<<endl; |
196 | system ( "pause" ); |
197 | } |
198 | else if (choiced == 6) |
199 | { |
200 | system ( "cls" ); |
201 | int dep = depth(rootNode); |
202 | cout<< "此二叉树的深度为" <<dep<<endl; |
203 | system ( "pause" ); |
204 | } |
205 | else if (choiced == 7) |
206 | { |
207 | system ( "cls" ); |
208 | cout<< "二叉树已被消毁!\n" ; |
209 | destroy(rootNode); |
210 | cout<<endl; |
211 | system ( "pause" ); |
212 | } |
213 | else |
214 | { |
215 | system ( "cls" ); |
216 | cout<< "\n\n\n\n\n\t错误选择!\n" ; |
217 | } |
218 | |
219 | } |
220 | } |