就以PTA上一道题为例:
题目要求由先序,中序序列来创建二叉树,在这里先不考虑算法部分,仅就二叉树的建立部分稍做分析。
1.不传参
#include<iostream>
using namespace std;
typedef struct Bintree {
int element;
Bintree* left;
Bintree* right;
}*BT, BN;
BT creat_bintree( int lenght, int* pre, int* mid)
{
BT T = new BN;
if (lenght == 1)
{
T->element = *pre;
T->left = NULL;
T->right = NULL;
return T;
}
T->element = *pre;
int root = 0;
while (mid[root] != pre[0] && root < lenght)
root++;//找出中序中root位置
if (root) T->left =creat_bintree( root, pre + 1, mid);
if (lenght - root - 1)T->right= creat_bintree( lenght - 1 - root, pre + root + 1, mid + root + 1);
return T;
}
int main()
{
int n;
cin >> n;
int a[100], b[100];
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
cin >> b[i];
}
BT T=creat_bintree(n, a, b);
cout << T->right->left->element;
}
这里用到指针函数,在申请内存部分笔者真是困惑了许久。(首先为申请一个树节点的空间,为树节点的数据域赋值,再将树节点的左右儿子依次递归遍历)笔者一再在疑惑在递归调用creat_bintree函数是会再次申请新的树节点,而再次申请的树节点与上次申请的树节点因为名称相同是否会产生冲突(将上个节点覆盖),这样递归到最后也是仅有一个节点。后来在一位学长的帮助下笔者才知道是多虑了。()接着就是返回值的问题,代码写道length=1时返回,也就是遍历到叶节点才返回。直观上来看就一个返回值就行,函数末尾似乎不需要加return 。但是返回最开始时的思路,我们在中序序列中找到根节点也就把中序序列分成三部分(左子树 根 右子树),递归的过程就是将左右子树作为根的左右节点,在递归左子树时申请新的节点,此时lenght!=1,也就是此次递归无返回值,那么根的左子树也就不会创建。
2.传参
这里给出指针引用和二级指针两种写法。
1).引用指针传参
#include<iostream>
using namespace std;
typedef struct Bintree {
int element;
Bintree* left;
Bintree* right;
}*BT,BN;
void creat_bintree(BN * &T ,int lenght, int* pre, int* mid)
{
T = new BN;
if (lenght == 1)
{
T->element = *pre;
T->left = NULL;
T->right = NULL;
return ;
}
T->element = *pre;
int root = 0;
while (mid[root] != pre[0] && root < lenght)
root++;//找出中序中root位置
if (root) creat_bintree(T->left,root, pre + 1, mid);
if (lenght - root - 1) creat_bintree(T->right,lenght - 1 - root, pre + root+1, mid + root + 1);
}
int main()
{
int n;
cin >> n;
int a[100], b[100];
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
cin >> b[i];
}
BT T;
creat_bintree(T,n, a, b);
cout << T->right->element;
}
2).二级指针直接传参
#include<iostream>
using namespace std;
typedef struct Bintree {
int element;
Bintree* left;
Bintree* right;
}*BT,BN;
void creat_bintree(BN** T ,int lenght, int* pre, int* mid)
{
(*T) = new BN;
if (lenght == 1)
{
(*T)->element = *pre;
(*T)->left = NULL;
(*T)->right = NULL;
return ;
}
(*T)->element = *pre;
int root = 0;
while (mid[root] != pre[0] && root < lenght)
root++;//找出中序中root位置
if (root) creat_bintree(&(*T)->left, root, pre + 1, mid);
if (lenght - root - 1) creat_bintree(&(*T)->right,lenght - 1 - root, pre + root+1, mid + root + 1);
}
int main()
{
int n;
cin >> n;
int a[100], b[100];
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
cin >> b[i];
}
BT T=new BN;
creat_bintree( &T ,n, a, b);
cout << T->right->element;
}
指向引用指针传参中Bintree* &T从字面上可以看作指向结构体Bintree的指针的地址 ((&(Bintree* T)这里这样想只是为了方便理解,实际的结合方式是这样(Bintree*) (&T) ),二级指针传参中Bintree** T代表T就是一个二级指针。引用和指针的相同点:两者都是地址的概念,指针指向一块儿内存,其内容为所指内存的地址;引用是某块儿内存的别名
代码中可以看出在书写上引用更为简洁。