首先我们需要先了解一下什么叫做引用传递
老规矩先上代码
#include<stdio.h>
//这里我们设了两个引用,一个是b是a的引用,一个是c是b的引用,即a就是b就是c,三者等价
void f1(int&);
void f2(int&);
int main(){
int a=3;
f1(a);
printf("%p\n",&a);
printf("%d\n",a); //最终c改变了a的值
return 0;
}
void f1(int&b){ //这个符号&前面表示数据类型,其后面表示引用的名字,即b是a的引用(在调试过程中,可以看到在还没有执行语句b=4时,b就有初值为3,也从反面说明了b是a的引用)
b=4;
printf("%p\n",&b);
f2(b);
}
void f2(int&c){ //同理,c是b的引用(在还没有执行c=5时,c已经有初值4了)
c=5;
printf("%p\n",&c);
}
最终运行的结果为:
从结果可以看出,a,b,c三者共用同一存储单元.
最后附上一个详解链接
第二部分即为二叉排序树的代码
#include <stdio.h>
#include <malloc.h>
typedef int Datatype;
//组成二叉排序树需要两个部分,一个是关键字,一个是左,右指针
typedef struct Node
{
Datatype key;
struct Node *left, *right;
} NODE;
bool search(NODE *&, Datatype, NODE *, NODE *&);
void insertBST(NODE *&, Datatype);
void deleteBST(NODE *&, Datatype);
void deleteNODE(NODE *&, Datatype);
int main()
{
NODE *p = NULL;
insertBST(p, 15);
insertBST(p, 30);
insertBST(p, 10);
insertBST(p, 5);
insertBST(p, 12);
insertBST(p, 50);
insertBST(p, 20);
insertBST(p, 16);
insertBST(p, 25);
insertBST(p, 28);
insertBST(p, 26);
deleteBST(p, 30);
return 0;
}
/* 如果在二叉排序树中没有找到关键字,则调用insertBST函数
这里的&表示引用 */
void insertBST(NODE *&T, Datatype key)
{
NODE *f = NULL; //每次都将f赋值为0(因为每次函数都是从根节点出发,并且默认根节点的父节点为NULL)
NODE *p; //p指向f所指向的节点(即待插入节点)
if (!search(T, key, f, p))
{ //search返回false,即没有找到关键字元素,即进行插入操作
NODE *pNew = (NODE *)malloc(sizeof(NODE));
pNew->left = pNew->right = NULL;
pNew->key = key; //上面三步都是为了生成一个值为关键字的节点
if (!p){
T = pNew; //只有一种情况就是空树(即刚开始建树)
}
else if (key < p->key){ //关键字比待插入节点小,则连接到其左子树上
p->left = pNew;
}
else if (key > p->key){
p->right = pNew;
}
}
}
//查找某个元素是否二叉树中(T指向二叉树的根节点,key代表关键字,f指向T的父亲节点,这里的p是引用,即等价于NODE *p中的p)
bool search(NODE *&T, Datatype key, NODE *f, NODE *&p)
{
if (T == NULL){ //两种情况:1.空树(即刚开始建树) 2.递归查询过程中,该节点上无左子树(或右子树)[即查询不到该元素]
p = f;
return false;
}
else if (key < T->key){ //关键字比当前节点元素小,则从当前节点的左子树开始递归查询
search(T->left, key, T, p); //将当前节点左子树节点T->left递归查询(这里的第三项即为f=T,意思是将当前节点T保存在f中,则进行递归查询后f就为此时节点的父节点)
}
else if (key > T->key){
search(T->right, key, T, p);
}
else{ //关键字与当前节点相同
p = T;
return true;
}
}
//查找二叉树中是否存在关键字key的节点,这里的&为引用
void deleteBST(NODE *&T, Datatype key)
{
if (T){
if (T->key == key){
deleteNODE(T, key);
}
else if (key<T->key){
deleteBST(T->left, key);
}
else deleteBST(T->right, key);
}
}
/* 删除关键字节点:有四种情况:1.待删节点为叶子节点
2.待删节点只有左子树
3.待删节点只有右子树
4.待删节点既有左子树也有右子树 */
void deleteNODE(NODE *&T, Datatype key) //这里的T很巧妙,既是待删节点的指针也是其父节点的左或者右指针
{
NODE *q; //用来保存待删节点的父节点(针对的是最后一种情况)
NODE *s; //保存待删节点(针对最后一种情况)
if (T->left == NULL && T->right == NULL){
T=NULL;
}
else if (T->left == NULL){
q = T;
T = T->right;
free(q);
}
else if (T->right == NULL){
q = T;
T = T->left;
free(q);
}
else{ //此处又分为两种情况:1.待删节点的左子树上没有右子树 2.待删左子树上有右子树
q = T;
s = T->left;
if (!s->right){ //首先判断待删节点的左子树节点上是否存在右子树
T = s->left; //如果没有右子树,则直接挂上
}
else{ //第二种情况有右子树,则一直向右移动,找到其最右节点
while (s->right){
q = s;
s = s->right;
}
T->key = s->key; //将最右节点的值赋给待删节点,然后判断其是否有子树节点
if (s->left == NULL && s->right == NULL){ //没有子树,则直接赋为空
free(s);
q->right = NULL;
}
else{ //有左子树(此时不可能有右子树,因为之前找到的就是最右节点),然后挂上去即可
q->right = s->left;
free(s);
}
}
}
}