У меня есть вопрос относительно этой части кода. Node* &head
, в функции insert(), мне трудно понять смысл этого. Является ли это "ссылкой на указатель на структуру узла"?
Но почему здесь getDepth(Node *head)
он использует Node *head
? Это хорошая практика? какой лучший способ написать, если это возможно?
Спасибо!
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 100;
struct Node{
int key;
Node *lchild, *rchild, *parent;
};
Node *head, *p, node[maxn];
int cnt;
void init(){
head = p = NULL;
memset(node, '\0', sizeof(node));
cnt = 0;
}
void insert(Node* &head, int x){
if(head == NULL){
node[cnt].key = x;
node[cnt].parent = p;
head = &node[cnt++];
return;
}
p = head;
if(x < head->key)
insert(head->lchild, x);
else
insert(head->rchild, x);
}
int d = 0, num = 0, dep[maxn];
void getDepth(Node *head){
if(head == NULL) return;
++d;
getDepth(head->lchild);
if(head->lchild == NULL && head->rchild == NULL)
dep[num++] = d;
getDepth(head->rchild);
--d;
}
bool isBalance(Node *head){
if(head == NULL) return true;
getDepth(head);
int max = dep[0], min = dep[0];
for(int i=0; i<num; ++i){
if(dep[i]>max) max = dep[i];
if(dep[i]<min) min = dep[i];
}
if(max-min > 1) return false;
else return true;
}
int main(){
init();
int a[] = {
5, 3, 8, 1, 4, 7, 10, 2, 6, 9, 11, 12
};
for(int i=0; i<12; ++i)
insert(head, a[i]);
cout<<isBalance(head)<<endl;
return 0;
}
Если вы передаете Node *head
вместо Node* &head
, и если "head" будет изменен, изменение не будет доступно в main
функции.
Если вы хотите, чтобы эти изменения были доступны, вы return head
или пропустите Node* &head
или Node **head
.
В getDepth()
нет необходимости менять указатель "head". Итак, прохождение Node *head
отлично работает.
Именно это и есть: ссылка на указатель на Node
. Он позволяет передавать в Node*
по ссылке, так что, когда вы изменяете указатель внутри функции, модификация будет видна снаружи.
Простой пример с эталонным параметром:
void inc(int& x) {
x++;
}
Если у меня есть переменная int y = 0;
, передайте его с помощью inc(y)
, а затем проверьте значение y
после этого, оно будет иметь значение 1
. Если параметр не был ссылочным типом, значение было бы 0
, потому что только копия внутри inc
была бы изменена.
Ваше дело точно так же. Вы передаете Node*
по ссылке, чтобы вы могли изменить указатель и видеть его снаружи.
Эта конструкция означает ссылку на переменную с типом Node *. Проблема в том, что если вы просто объявляете этот параметр функции insert как Node *, то внутри функции этот параметр bahaves как локальная переменная. Таким образом, любые изменения в нем будут потеряны после выхода из функции. Таким образом, в этом случае исходная переменная голова не будет изменена. Передача указателя по ссылке гарантирует, что любые изменения в голове внутри функции будут сохранены в исходной переменной.
Вы смотрите на ссылку на указатель.
http://en.wikipedia.org/wiki/Reference_(C%2B%2B)
Я бы избегал использовать ссылки, так как они неотличимы от передачи чего-то по значению при вызове.
Человек, который написал этот код, является рывком и написал нечитаемый код. Просто ужасно.
Однако Node * & head является ссылкой на указатель на узел. Таким образом, в основном он передает указатель на голову по ссылке, поэтому вы можете изменить значение главы ptr.
Например:
Node *A = NULL;
insert(A,10);
//now A has changed, A != NULL;
struct List { Node* head; };
а затем insert()
будет принимать List&
. Или даже просто typedef Node* List;