Наблюдение и находка, ПОЧЕМУ ...
Я решил провести несколько экспериментов и сделать какой-то вывод,
НАБЛЮДЕНИЕ 1- Если связанный список не пуст, то мы можем добавить в него узлы (очевидно, в конце), используя только один указатель.
int insert(struct LinkedList *root, int item){
struct LinkedList *temp = (struct LinkedList*)malloc(sizeof(struct LinkedList));
temp->data=item;
temp->next=NULL;
struct LinkedList *p = root;
while(p->next!=NULL){
p=p->next;
}
p->next=temp;
return 0;
}
int main(){
int m;
struct LinkedList *A=(struct LinkedList*)malloc(sizeof(struct LinkedList));
//now we want to add one element to the list so that the list becomes non-empty
A->data=5;
A->next=NULL;
cout<<"enter the element to be inserted\n"; cin>>m;
insert(A,m);
return 0;
}
Его легко объяснить (Basic). В нашей главной функции есть указатель, который указывает на первый узел (корень) списка. В функции insert()
мы передаем адрес корневого узла и, используя этот адрес, достигаем конца списка и добавляем в него узел. Таким образом, мы можем заключить, что если у нас есть адрес переменной в функции (не основной функции), мы можем сделать постоянные изменения в значении этой переменной из этой функции, что отражается в основной функции.
НАБЛЮДЕНИЕ 2- Указанный выше метод добавления узла не удался, когда список был пустым.
int insert(struct LinkedList *root, int item){
struct LinkedList *temp = (struct LinkedList*)malloc(sizeof(struct LinkedList));
temp->data=item;
temp->next=NULL;
struct LinkedList *p=root;
if(p==NULL){
p=temp;
}
else{
while(p->next!=NULL){
p=p->next;
}
p->next=temp;
}
return 0;
}
int main(){
int m;
struct LinkedList *A=NULL; //initialise the list to be empty
cout<<"enter the element to be inserted\n";
cin>>m;
insert(A,m);
return 0;
}
Если вы продолжите добавлять элементы и, наконец, отобразите список, то обнаружите, что список не претерпел изменений, и все же он пуст.
Вопрос, который пришел мне в голову, был в этом случае, мы также передаем адрес корневого узла, тогда почему модификации не происходят как постоянные модификации, и список в основной функции не претерпевает изменений. ЗАЧЕМ? ЗАЧЕМ? ЗАЧЕМ?
Затем я заметил одну вещь: когда я пишу A=NULL
, адрес A
становится 0. Это означает, что теперь A
не указывает ни на какое место в памяти. Поэтому я удалил строку A=NULL;
и внес некоторые изменения в функцию вставки.
некоторые модификации, (ниже insert()
функция может добавлять только один элемент в пустой список, только что написала эту функцию для целей тестирования)
int insert(struct LinkedList *root, int item){
root= (struct LinkedList *)malloc(sizeof(struct LinkedList));
root->data=item;
root->next=NULL;
return 0;
}
int main(){
int m;
struct LinkedList *A;
cout<<"enter the element to be inserted\n";
cin>>m;
insert(A,m);
return 0;
}
вышеприведенный метод также не работает, потому что в функции insert()
root сохраняет тот же адрес, что и A
в функции main()
, но после строки root= (struct LinkedList *)malloc(sizeof(struct LinkedList));
адрес, сохраненный в root
, изменяется. Таким образом, теперь root
(в функции insert()
) и A
(в функции main()
) хранят разные адреса.
Таким образом, правильная конечная программа будет
int insert(struct LinkedList *root, int item){
root->data=item;
root->next=NULL;
return 0;
}
int main(){
int m;
struct LinkedList *A = (struct LinkedList *)malloc(sizeof(struct LinkedList));
cout<<"enter the element to be inserted\n";
cin>>m;
insert(A,m);
return 0;
}
Но нам не нужны две разные функции для вставки: одна, когда список пуст, и другая, когда список не пуст. Теперь приходит двойной указатель, который делает вещи проще.
Одна вещь, которую я заметил, что важно, это то, что указатели хранят адрес
и при использовании с '*' они дают значение по этому адресу, но указатели
сами имеют свой адрес.
Теперь вот полная программа и позже объясним понятия.
int insert(struct LinkedList **root,int item){
if(*root==NULL){
(*root)=(struct LinkedList *)malloc(sizeof(struct LinkedList));
(*root)->data=item;
(*root)->next=NULL;
}
else{
struct LinkedList *temp=(struct LinkedList *)malloc(sizeof(struct LinkedList));
temp->data=item;
temp->next=NULL;
struct LinkedList *p;
p=*root;
while(p->next!=NULL){
p=p->next;
}
p->next=temp;
}
return 0;
}
int main(){
int n,m;
struct LinkedList *A=NULL;
cout<<"enter the no of elements to be inserted\n";
cin>>n;
while(n--){
cin>>m;
insert(&A,m);
}
display(A);
return 0;
}
Ниже приведены наблюдения,
1. root хранит адрес указателя A (&A)
, *root
хранит адрес, сохраненный указателем A
, а **root
хранит значение по адресу, сохраненному A
. На простом языке root=&A
, *root= A
и **root= *A
.
2. если мы напишем *root= 1528
, то это означает, что значение по адресу, хранящемуся в root
, становится 1528, и поскольку адрес, сохраненный в root
, является адресом указателя A (&A)
, то есть теперь A=1528
(т. Е. Адрес, сохраненный в A
, равен 1528), и это изменение является постоянным.
всякий раз, когда мы меняем значение *root
, мы действительно меняем значение по адресу, хранящемуся в root
, а с root=&A
(адрес указателя A
) мы косвенно меняем значение A
или адрес, сохраненный в A
.
так что теперь, если A=NULL
(список пуст) *root=NULL
, таким образом, мы создаем первый узел и сохраняем его адрес в *root
, то есть косвенно сохраняем адрес первого узла в A
. Если список не пустой, все то же самое, что и в предыдущих функциях с использованием одного указателя, за исключением того, что мы изменили корень на *root
, поскольку то, что было сохранено в корне, теперь хранится в *root
.