#c# #doubly-linked-list #deep-copy
#c# #дважды связанный список #глубокое копирование
Вопрос:
Я исследовал онлайн, что встроенный LinkedList является двусвязным списком в C #. Я также исследовал метод LinkedList.Remove(LinkedListNode). Но я все еще не мог найти ответ на свой вопрос. Ниже приведен фрагмент кода:
public string DequeueCat()
{
LinkedListNode<string> temp = animals.First;
while (temp != null amp;amp; temp.Value.Contains("Cat") == false)
{
temp = temp.Next;
}
if (temp!=null amp;amp; temp.Value.Contains("Cat"))
{
animals.Remove(temp);
return temp.Value;
}
else
{
Console.WriteLine("No more Cats available");
return null;
}
}
Переменная animals
имеет тип LinkedList<string>
.
Что именно происходит, когда мы создаем новый LinkedListNode<string>
экземпляр с animals.First
помощью ? Например LinkedListNode<string> temp = animals.First;
.
Происходит ли глубокое копирование и исходный LinkedList (на который указывает animals.First
), копируется temp
в новое место в куче?
Кроме того, когда мы пишем animals.Remove(temp)
, temp
LinkListNode уничтожается. И соответствующее значение удаляется из animals
LinkedList .
Ниже приведено окно просмотра перед выполнением animals.Remove(temp)
—
И ниже приведено окно просмотра ПОСЛЕ выполнения animals.Remove(temp)
—
Мой вопрос в том, почему temp
после выполнения уничтожается animals.Remove(temp)
? Кроме того, если temp
он был создан в отдельном месте в куче (по сравнению с исходным LinkedList), то откуда мы знаем, что удаление temp
из исходного animals
LinkedList приведет к удалению соответствующего элемента из animals
LinkedList?
Ниже приведен весь код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AnimalShelter
{
class AnimalsShelter
{
//This class will have the following functions:
//Enqueue, DequeueAny, DeQueueDog, DeQueueCat
//Implement queue using C# inbuilt linked list.
LinkedList<string> animals = new LinkedList<string>();
public void Enqueue(string animal)
{
animals.AddLast(animal);
}
public string DequeueAny()
{
LinkedListNode<string> firstAnimal = animals.First;
if (firstAnimal != null)
{
animals.RemoveFirst();
return firstAnimal.Value;
}
else
{
Console.WriteLine("No more animanls left in queue.");
return null;
}
}
public string DequeueDog()
{
LinkedListNode<string> temp = animals.First;
while(temp!=null amp;amp; temp.Value.Contains("Dog")==false)
{
temp = temp.Next;
}
if(temp!=null amp;amp; temp.Value.Contains("Dog"))
{
animals.Remove(temp);
return temp.Value;
}
else
{
Console.WriteLine("No more Dogs available");
return null;
}
}
public string DequeueCat()
{
LinkedListNode<string> temp = animals.First;
while (temp != null amp;amp; temp.Value.Contains("Cat") == false)
{
temp = temp.Next;
}
if (temp!=null amp;amp; temp.Value.Contains("Cat"))
{
animals.Remove(temp);
return temp.Value;
}
else
{
Console.WriteLine("No more Cats available");
return null;
}
}
}
class Program
{
static void Main(string[] args)
{
AnimalsShelter shelter = new AnimalsShelter();
shelter.Enqueue("Dog1");
shelter.Enqueue("Dog2");
shelter.Enqueue("Cat1");
shelter.Enqueue("Dog3");
shelter.Enqueue("Cat2");
shelter.Enqueue("Cat3");
Console.WriteLine(shelter.DequeueCat());
Console.WriteLine(shelter.DequeueAny());
Console.WriteLine(shelter.DequeueDog());
Console.WriteLine(shelter.DequeueCat());
Console.WriteLine(shelter.DequeueAny());
Console.WriteLine(shelter.DequeueAny());
}
}
}
Любой свет на это очень ценится. Спасибо!
Комментарии:
1. Помогает ли это: referencesource.microsoft.com/#system/compmod/system /…
2. @SeanReid, спасибо за ваш указатель! Итак, когда мы говорим
LinkedListNode<string> temp = animals.First
;. Обаtemp
иanimals.First
находятся в стеке, и они указывают на то жеLinkedListNode
самое в куче. Правильно? Кроме того,animals
переменная находится в стеке и указываетLinkedList
на в куче. И когда мы говоримanimals.Remove(temp)
,LinkedListNode
указываемыйtemp
удаляется изanimals
. Правильно? Также иtemp
переменная, иanimals
переменная находятся в стеке, и они указывают наLinkedListNode
иLinkedList
в куче, соответственно. Правильно?
Ответ №1:
Переменная animals имеет тип
LinkedList<string>
. Что именно происходит, когда мы создаем новыйLinkedListNode<string>
экземпляр сanimals.First
помощью ? НапримерLinkedListNode<string> temp = animals.First;
. Происходит ли глубокое копирование
Нет. Все, что вы сделали, это скопировали ссылку LinkedListNode<string> temp = animals.First;
Кроме того, когда мы пишем
animals.Remove(temp)
, tempLinkListNode
уничтожается.
Нет. Он не уничтожается, однако его ссылки удаляются. Это все та же ссылка.
Мой вопрос в том, почему temp уничтожается после выполнения animals .Удалить (temp)?
Нет. Еще раз, он не уничтожается. однако его ссылки удаляются.
Кроме того, если temp был создан в отдельном месте в куче
Нет. Он не был создан в отдельном месте в куче, все, что вы сделали, это скопировали ссылку.
тогда откуда мы знаем, что удаление temp из исходного, animals LinkedList приведет к удалению соответствующего элемента из animals LinkedList
Мы знаем, потому что это был тот же объект / та же ссылка.
Вот примерный код для Remove
. Как вы можете видеть, здесь нет волшебства:
internal void InternalRemoveNode(LinkedListNode<T> node)
{
...
if ( node.next == node)
head = null;
else
{
node.next.prev = node.prev;
node.prev.next = node.next;
if ( head == node)
head = node.next;
}
node.Invalidate();
count--;
version ;
}
Дальнейшее чтение
Ссылочные типы (C # Reference)
В C # есть два вида типов: ссылочные типы и типы значений. Переменные ссылочных типов хранят ссылки на свои данные (объекты), в то время как переменные типов значений непосредственно содержат их данные. С ссылочными типами две переменные могут ссылаться на один и тот же объект; поэтому операции над одной переменной могут влиять на объект, на который ссылается другая переменная. С типами значений каждая переменная имеет свою собственную копию данных, и операции с одной переменной не могут влиять на другую (за исключением случаев переменных параметров in, ref и out; см. Модификатор параметров in, ref и out).
Комментарии:
1. Спасибо за ваш ответ! Итак, когда мы говорим
LinkedListNode<string> temp = animals.First;
. Обаtemp
иanimals.First
находятся в стеке, и они указывают на то жеLinkedListNode
самое в куче. Правильно? Кроме того,animals
переменная находится в стеке и указываетLinkedList
на в куче. И когда мы говоримanimals.Remove(temp)
,LinkedListNode
указываемыйtemp
удаляется изanimals
. Правильно? Также иtemp
переменная, иanimals
переменная находятся в стеке, и они указывают наLinkedListNode
иLinkedList
в куче, соответственно. Правильно?