我正在尝试练习问题并在C#中实现了一个通用的单链接列表,其头部是私有变量 -
/// <summary>
/// Root of the linked list
/// </summary>
private Node head;
public class Node
{
private object data;
private Node next;
/// <summary>
/// Data contained in the node
/// </summary>
public object Data
{
get
{
return data;
}
set
{
data = value;
}
}
/// <summary>
/// Reference to the next node of the singly linked list
/// </summary>
public Node Next
{
get
{
return next;
}
set
{
next = value;
}
}
}
现在我正在尝试解决另一个问题,我需要使用这个单独链接的列表来实现一个用于猫狗避难所的FIFO队列。这个队列应该允许出列入最后排队的猫/狗,但另外还有两种方法 -
DequeueCat - 即使它不是队列的最后一个节点
,也会使最旧的队列出列队列DequeueDog - 将最旧的狗排队,即使它不是队列的最后一个节点
我不想在SinglyLinkedList类中实现这些方法,而是创建一个名为CatDogShelterQueue的单独类 -
但是为了实现DequeueCat / Dog方法,我需要遍历链表并到达最老的Cat / Dog节点。
我知道有几种方法可以做到这一点 -
protected
代替private
并继承SinglyLinkedList作为CatDogShelterQueue的基类internal
并通过引用SinglyLinkedList类型的变量来使用它 - private SinglyLinkedList queue;
目前,我选择了第二种选择,但想知道在这种情况下最佳做法是什么。
我目前的最终解决方案如下 -
SinglyLinkedList
/* Program: Singly Linked List implementation in C#
*
* Date: 12/24/2015
*/
using System;
namespace CrackingTheCodingInterview
{
/// <summary>
/// A node of the singly linked list
/// It contains data in generic object type and points to next node in the list
/// </summary>
public class Node
{
private object data;
private Node next;
/// <summary>
/// Data contained in the node
/// </summary>
public object Data
{
get
{
return data;
}
set
{
data = value;
}
}
/// <summary>
/// Reference to the next node of the singly linked list
/// </summary>
public Node Next
{
get
{
return next;
}
set
{
next = value;
}
}
}
/// <summary>
/// Implementation of a singly linked list
/// </summary>
public partial class SinglyLinkedList
{
/// <summary>
/// Root of the linked list
/// </summary>
internal Node head;
/// <summary>
/// Creates a new node for inserting in singly linked list
/// <param name="d">Data to be inserted in node</param>
/// <returns>Returns the created node to be added in singly linked list</returns>
/// </summary>
private Node CreateNewNode(object d)
{
Node newNode = new Node();
newNode.Data = d;
newNode.Next = null;
return newNode;
}
/// <summary>
/// Default constructor of singly linked list
/// </summary>
public SinglyLinkedList()
{
head = null;
}
/// <summary>
/// Insert a node to the start of singly linked list
/// </summary>
/// <param name="d">Data to be inserted in the singly linked list</param>
public void Insert(object d)
{
Node newNode = CreateNewNode(d);
if (head == null)
{
head = newNode;
}
else
{
newNode.Next = head;
head = newNode;
}
}
/// <summary>
/// Traverse and print all the nodes of singly linked list
/// </summary>
public void Print()
{
Node temp = head;
while (temp != null)
{
Console.Write("{0}->", temp.Data);
temp = temp.Next;
}
Console.WriteLine();
}
/// <summary>
/// <param name="d">Data to be searched in all the nodes of a singly linked list</param>
/// Traverses through each node of a singly linked list and searches for an element
/// <returns>Node if the searched element exists else null </returns>
/// </summary>
public Node Search(object d)
{
Node temp = head;
while (temp != null)
{
if (temp.Data.Equals(d))
{
return temp;
}
temp = temp.Next;
}
return null;
}
/// <summary>
/// Returns head of the linked list if it exists else null
/// <returns>Data in head of linked list if it exists else null</returns>
/// </summary>
public object DeleteHead()
{
if (head != null)
{
Node temp = head;
head = head.Next;
return temp.Data;
}
else
{
return null;
}
}
/// <summary>
/// Peeks head of the linked list if it exists else null
/// <returns>Data in head of linked list if it exists else null</returns>
/// </summary>
public object PeekHead()
{
if (head != null)
{
return head.Data;
}
else
{
return null;
}
}
/// <summary>
/// Checks if the singly linked list is empty
/// <returns>true if linked list is empty else false</returns>
/// </summary>
public bool IsEmpty()
{
return (head == null);
}
/// <summary>
/// Inserts the element at the end of the linked list
/// <param name="d">Element to be inserted at the end</param>
/// </summary>
public void InsertEnd(object d)
{
Node newNode = CreateNewNode(d);
Node temp = head;
if (head == null)
{
head = newNode;
}
else
{
while (temp.Next != null)
{
temp = temp.Next;
}
temp.Next = newNode;
}
}
/// <summary>
/// Deletes the last node of the linked list
/// </summary>
/// <returns>Last node of linked list</returns>
public object DeleteEnd()
{
if (head == null || head.Next == null)
{
return DeleteHead();
}
else
{
Node temp = head;
while (temp.Next.Next != null)
{
temp = temp.Next;
}
object del = temp.Next.Data;
temp.Next = null;
return del;
}
}
/// <summary>
/// Deletes second last element of linked list
/// <returns>Second last element of linked list</returns>
/// </summary>
public object DeleteSecondLast()
{
if (head == null || head.Next == null)
{
return null;
}
else
{
if (head.Next.Next == null)
{
object del = head.Data;
head = head.Next;
return del;
}
else
{
Node temp = head;
while (temp.Next.Next.Next != null)
{
temp = temp.Next;
}
object del = temp.Next.Data;
temp = temp.Next.Next;
return del;
}
}
}
}
}
CatDogShelterQueue
/* Program: To implement a queue for cat and dog shelter
*
* Date: 1/1/2016
*/
using System;
namespace CrackingTheCodingInterview
{
/// <summary>
/// Class for a cat and dog shelter queue
/// </summary>
public class CatDogShelterQueue
{
/// <summary>
/// Class for storing type and number of cat/dog
/// </summary>
public class CatDog
{
internal CatDogType type;
internal int num;
/// <summary>
/// Constructor for initializing CatDog with its type and number
/// </summary>
public CatDog(int n, CatDogType t)
{
num = n;
type = t;
}
}
private SinglyLinkedList queue;
/// <summary>
/// Constructor initializing a singly linked list acting as a FIFO queue
/// </summary>
public CatDogShelterQueue()
{
queue = new SinglyLinkedList();
}
/// <summary>
/// <param name="d"> Cat/Dog Number </param>
/// <param name="c"> Type - Cat or Dog </param>
/// </summary>
public void enqueue(object d, CatDogType c)
{
CatDog cd = new CatDog((int)d, c);
queue.Insert(cd);
}
/// <summary>
/// Dequeueing last animal - cat or dog
/// </summary>
/// <returns>Cat or Dog oldest arrival</returns>
public CatDog dequeueAny()
{
return (CatDog)queue.DeleteEnd();
}
/// <summary>
/// Dequeueing the oldest cat
/// </summary>
/// <returns>Oldest entered cat</returns>
public CatDog dequeueCat()
{
Node lastCat = null;
Node temp = queue.head;
while(temp != null)
{
if (((CatDog)temp.Data).type == CatDogType.Cat)
{
lastCat = temp;
}
temp = temp.Next;
}
if(lastCat.Next == null)
{
return (CatDog)queue.DeleteEnd();
}
else
{
CatDog del = (CatDog)lastCat.Data;
lastCat.Data = lastCat.Next.Data;
lastCat.Next = lastCat.Next.Next;
return del;
}
}
/// <summary>
/// Dequeueing the oldest dog
/// </summary>
/// <returns>Oldest entered dog</returns>
public CatDog dequeueDog()
{
Node lastCat = null;
Node temp = queue.head;
while (temp != null)
{
if (((CatDog)temp.Data).type == CatDogType.Dog)
{
lastCat = temp;
}
temp = temp.Next;
}
if (lastCat.Next == null)
{
return (CatDog)queue.DeleteEnd();
}
else
{
CatDog del = (CatDog)lastCat.Data;
lastCat.Data = lastCat.Next.Data;
lastCat.Next = lastCat.Next.Next;
return del;
}
}
}
internal class CatDogShelterQueueTest
{
static void Main()
{
CatDogShelterQueue q = new CatDogShelterQueue();
q.enqueue(1, CatDogType.Cat);
q.enqueue(2, CatDogType.Dog);
q.enqueue(3, CatDogType.Cat);
q.enqueue(4, CatDogType.Dog);
q.enqueue(5, CatDogType.Cat);
Console.WriteLine("Dequeueing last animal: {0}", q.dequeueAny().num);
Console.WriteLine("Dequeueing last cat: {0}", q.dequeueCat().num);
Console.WriteLine("Dequeueing last dog: {0}", q.dequeueDog().num);
Console.ReadLine();
}
}
/// <summary>
/// Cat or Dog
/// </summary>
public enum CatDogType
{
/// <summary>
/// Cat
/// </summary>
Cat,
/// <summary>
/// Dog
/// </summary>
Dog
};
}