使用通用链表进行特定队列实现的最佳实践

时间:2016-01-02 05:06:38

标签: c# queue private singly-linked-list

我正在尝试练习问题并在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节点。

我知道有几种方法可以做到这一点 -

  1. 让'head'protected代替private并继承SinglyLinkedList作为CatDogShelterQueue的基类
  2. 制作'head'internal并通过引用SinglyLinkedList类型的变量来使用它 -
  3. 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
        };
    }
    

0 个答案:

没有答案