simonradev

FirstImplementationOfDoubleLinkedList

Jan 24th, 2017
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 19.78 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace DoubleLinkedListTest
  8. {
  9.     class DoubleLinkedListTest
  10.     {
  11.         static void Main(string[] args)
  12.         {
  13.             DoubleLinkedList<string> testLinkedList = new DoubleLinkedList<string>();
  14.             testLinkedList[0] = "1";
  15.             testLinkedList[1] = "2";
  16.             testLinkedList[2] = testLinkedList[0] + testLinkedList[1];
  17.             testLinkedList[3] = "as";
  18.         }
  19.     }
  20.  
  21.     /// <summary>
  22.     /// With the list you can collect and organize elements and data.
  23.     /// This is a dynamic implementation, which means that adding works fast but indexes dont.
  24.     /// </summary>
  25.     /// <typeparam name="TType">The type of elements you want to collect</typeparam>
  26.     public class DoubleLinkedList<TType>
  27.     {
  28.         /// <summary>
  29.         /// A single element from the list which holds a reference to the next and previous element.
  30.         /// </summary>
  31.         private class Node
  32.         {
  33.             /// <summary>
  34.             /// Holds the reference of the next Node.
  35.             /// </summary>
  36.             private Node next;
  37.             /// <summary>
  38.             /// Holds the reference of the previous Node.
  39.             /// </summary>
  40.             private Node previous;
  41.             /// <summary>
  42.             /// Holds the value of the current Node.
  43.             /// </summary>
  44.             private TType value;
  45.  
  46.             /// <summary>
  47.             /// Enables you you to set or get the next Node.
  48.             /// </summary>
  49.             public Node Next
  50.             {
  51.                 get { return this.next; }
  52.                 set { this.next = value; }
  53.             }
  54.  
  55.             /// <summary>
  56.             /// Enables you to get or set the previous Node.
  57.             /// </summary>
  58.             public Node Previous
  59.             {
  60.                 get { return this.previous; }
  61.                 set { this.previous = value; }
  62.             }
  63.  
  64.             /// <summary>
  65.             /// Enables you to get or set the value of the current Node.
  66.             /// </summary>
  67.             public TType Value
  68.             {
  69.                 get { return this.value; }
  70.                 set { this.value = value; }
  71.             }
  72.         }
  73.  
  74.         /// <summary>
  75.         /// Holds the first element of the collection and a reference to the next ones.
  76.         /// </summary>
  77.         private Node head;
  78.         /// <summary>
  79.         /// Holds the last element of the collection and a reference to the previous ones.
  80.         /// </summary>
  81.         private Node tail;
  82.         /// <summary>
  83.         /// Holds the number of elements which are currently in the list.
  84.         /// </summary>
  85.         private int count;
  86.  
  87.         /// <summary>
  88.         /// Sets the fields to their default values.
  89.         /// </summary>
  90.         public DoubleLinkedList()
  91.         {
  92.             this.count = 0;
  93.             this.head = default(Node);
  94.             this.tail = default(Node);
  95.         }
  96.  
  97.         /// <summary>
  98.         /// Holds the count of the elements in the list.
  99.         /// </summary>
  100.         public int Count
  101.         {
  102.             get { return this.count; }
  103.         }
  104.  
  105.         /// <summary>
  106.         /// Enables the lists elements to be accesed by index.
  107.         /// </summary>
  108.         /// <param name="index">The index of the element you want.</param>
  109.         /// <returns>The element at the index entered.</returns>
  110.         public TType this[int index]
  111.         {
  112.             get { return GetElementByIndex(index); }
  113.             set { AddElementToIndexOrOverrideExcistingElement(value, index); }
  114.         }
  115.  
  116.         /// <summary>
  117.         /// This is a method written to be used only from the proporty which enables indexing the list.
  118.         /// </summary>
  119.         /// <param name="elementToAdd">Adds or overwrites and element at an index.</param>
  120.         /// <param name="indexToAddIn">The index of the element you want to update or create.</param>
  121.         private void AddElementToIndexOrOverrideExcistingElement(TType elementToAdd, int indexToAddIn)
  122.         {
  123.             if (indexToAddIn < 0 || indexToAddIn > count)
  124.             {
  125.                 throw new InvalidOperationException("The index is out of the bounds of the list!!!");
  126.             }
  127.  
  128.             if (count == 0)
  129.             {
  130.                 head = new Node();
  131.                 head.Next = default(Node);
  132.                 head.Previous = default(Node);
  133.                 head.Value = elementToAdd;
  134.  
  135.                 tail = head;
  136.             }
  137.             else if (indexToAddIn == 0)
  138.             {
  139.                 head.Value = elementToAdd;
  140.  
  141.                 count--;
  142.             }
  143.             else if (indexToAddIn + 1 == count)
  144.             {
  145.                 tail.Value = elementToAdd;
  146.  
  147.                 count--;
  148.             }
  149.             else
  150.             {
  151.                 Node currNode = head;
  152.                 int currIndex = 1;
  153.                 while (currIndex != indexToAddIn)
  154.                 {
  155.                     currNode = currNode.Next;
  156.  
  157.                     currIndex++;
  158.                 }
  159.  
  160.                 try
  161.                 {
  162.                     currNode.Next.Value = elementToAdd;
  163.  
  164.                     count--;
  165.                 }
  166.                 catch (NullReferenceException)
  167.                 {
  168.                     Node toAdd = new Node();
  169.                     toAdd.Value = elementToAdd;
  170.  
  171.                     currNode.Next = toAdd;
  172.                     toAdd.Previous = currNode;
  173.  
  174.                     tail = toAdd;
  175.                 }
  176.             }
  177.  
  178.             count++;
  179.         }
  180.  
  181.         /// <summary>
  182.         /// Adds and element at the end of the list.
  183.         /// </summary>
  184.         /// <param name="elementToAdd">The element you want to add at the end.</param>
  185.         public void AddInTheEnd(TType elementToAdd)
  186.         {
  187.             if (head == default(Node))
  188.             {
  189.                 head = new Node();
  190.                 head.Previous = default(Node);
  191.                 head.Next = default(Node);
  192.                 head.Value = elementToAdd;
  193.  
  194.                 tail = head;
  195.             }
  196.             else
  197.             {
  198.                 Node toAdd = new Node();
  199.                 toAdd.Value = elementToAdd;
  200.  
  201.                 Node currNode = head;
  202.                 while (currNode.Next != default(Node))
  203.                 {
  204.                     currNode = currNode.Next;
  205.                 }
  206.  
  207.                 currNode.Next = toAdd;
  208.                 toAdd.Previous = currNode;
  209.  
  210.                 tail = toAdd;
  211.             }
  212.  
  213.             count++;
  214.         }
  215.  
  216.         /// <summary>
  217.         /// Adds an element at the beginning of the list.
  218.         /// Be careful with the order the elements where put in it may not be what you want.
  219.         /// </summary>
  220.         /// <param name="elementToAdd">The element you want to add in the beginning.</param>
  221.         public void AddInTheBeginning(TType elementToAdd)
  222.         {
  223.             if (head == default(Node))
  224.             {
  225.                 head = new Node();
  226.                 head.Previous = default(Node);
  227.                 head.Next = default(Node);
  228.                 head.Value = elementToAdd;
  229.  
  230.                 tail = head;
  231.             }
  232.             else
  233.             {
  234.                 Node toAdd = new Node();
  235.                 toAdd.Value = elementToAdd;
  236.                 toAdd.Next = head;
  237.  
  238.                 head.Previous = toAdd;
  239.                 head = toAdd;
  240.  
  241.                 Node currNode = head;
  242.                 while (currNode.Next != default(Node))
  243.                 {
  244.                     currNode = currNode.Next;
  245.                 }
  246.  
  247.                 tail = currNode;
  248.             }
  249.  
  250.             count++;
  251.         }
  252.  
  253.         /// <summary>
  254.         /// Adds an element at an index.
  255.         /// If you add at index [0] the element goes before the current element at index [0].
  256.         /// </summary>
  257.         /// <param name="elementToAdd">The element you want to add.</param>
  258.         /// <param name="indexToAddAt">The index you want to add the element in.</param>
  259.         public void AddAtIndex(TType elementToAdd, int indexToAddAt)
  260.         {
  261.             if (indexToAddAt < 0 || indexToAddAt > count)
  262.             {
  263.                 throw new InvalidOperationException(
  264.                     "You can't add at this position. It is out of the boundaries of the list!!!");
  265.             }
  266.  
  267.             Node toAdd = new Node();
  268.             toAdd.Value = elementToAdd;
  269.  
  270.             if (count == 0)
  271.             {
  272.                 head = new Node();
  273.                 head.Value = elementToAdd;
  274.                 head.Next = default(Node);
  275.                 head.Previous = default(Node);
  276.  
  277.                 tail = head;
  278.             }
  279.             else if (indexToAddAt == 0)
  280.             {
  281.                 head.Previous = toAdd;
  282.                 toAdd.Next = head;
  283.                 toAdd.Previous = default(Node);
  284.  
  285.                 head = toAdd;
  286.             }
  287.             else if (indexToAddAt == count)
  288.             {
  289.                 tail.Next = toAdd;
  290.                 toAdd.Previous = tail;
  291.                 toAdd.Next = default(Node);
  292.  
  293.                 tail = toAdd;
  294.             }
  295.             else
  296.             {
  297.                 Node currNode = head;
  298.                 int currIndex = 1;
  299.                 while (currIndex != indexToAddAt)
  300.                 {
  301.                     currNode = currNode.Next;
  302.  
  303.                     currIndex++;
  304.                 }
  305.  
  306.                 Node nextNode = currNode.Next;
  307.  
  308.                 toAdd.Next = nextNode;
  309.                 toAdd.Previous = currNode;
  310.  
  311.                 currNode.Next = toAdd;
  312.                 nextNode.Previous = toAdd;
  313.             }
  314.  
  315.             count++;
  316.         }
  317.  
  318.         /// <summary>
  319.         /// Adds a collection of elements in the index entered.
  320.         /// </summary>
  321.         /// <param name="index">The index where you want to insert the collection.</param>
  322.         /// <param name="elementsToAdd">The collection you want to insert in the index.</param>
  323.         public void AddRange(int index, params TType[] elementsToAdd)
  324.         {
  325.             if (index < 0 || index > count)
  326.             {
  327.                 throw new InvalidOperationException(
  328.                        "You can't add at this position. It is out of the boundaries of the list!!!");
  329.             }
  330.  
  331.             for (int currElement = 0; currElement < elementsToAdd.Length; currElement++)
  332.             {
  333.                 TType currElementToAdd = elementsToAdd[currElement];
  334.  
  335.                 AddAtIndex(currElementToAdd, index);
  336.  
  337.                 index++;
  338.             }
  339.         }
  340.  
  341.         /// <summary>
  342.         /// Checks if an element excists in the list or not.
  343.         /// </summary>
  344.         /// <param name="elementToCheck">The element you want to check.</param>
  345.         /// <returns>"True" if the seached element exists and "False" if it does not.</returns>
  346.         public bool Contains(TType elementToCheck)
  347.         {
  348.             bool containsItem = false;
  349.  
  350.             if (head.Value.Equals(elementToCheck))
  351.             {
  352.                 containsItem = true;
  353.  
  354.                 return containsItem;
  355.             }
  356.             else if (tail.Value.Equals(elementToCheck))
  357.             {
  358.                 containsItem = true;
  359.  
  360.                 return containsItem;
  361.             }
  362.             else
  363.             {
  364.                 Node currNode = head.Next;
  365.                 while (!currNode.Equals(tail))
  366.                 {
  367.                     if (currNode.Value.Equals(elementToCheck))
  368.                     {
  369.                         containsItem = true;
  370.  
  371.                         return containsItem;
  372.                     }
  373.  
  374.                     currNode = currNode.Next;
  375.                 }
  376.             }
  377.  
  378.             return containsItem;
  379.         }
  380.  
  381.         /// <summary>
  382.         /// Removes the first occurrency of an element.
  383.         /// </summary>
  384.         /// <param name="elementToRemove">The element you want to remove.</param>
  385.         public void RemoveFirst(TType elementToRemove)
  386.         {
  387.             if (count == 0)
  388.             {
  389.                 throw new InvalidOperationException("The list is empty!!! Try adding something first!!!");
  390.             }
  391.  
  392.             Node currNode = head;
  393.             if (!currNode.Value.Equals(elementToRemove))
  394.             {
  395.                 try
  396.                 {
  397.                     while (!currNode.Next.Value.Equals(elementToRemove))
  398.                     {
  399.                         currNode = currNode.Next;
  400.                     }
  401.                 }
  402.                 catch (NullReferenceException)
  403.                 {
  404.                     throw new InvalidOperationException("No such element excists!!!");
  405.                 }
  406.  
  407.                 try
  408.                 {
  409.                     Node prevNode = currNode;
  410.                     Node nextNode = currNode.Next.Next;
  411.                     prevNode.Next = nextNode;
  412.                     nextNode.Previous = prevNode;
  413.                 }
  414.                 catch (NullReferenceException)
  415.                 {
  416.                     currNode.Next = default(Node);
  417.                     tail = currNode;
  418.                 }
  419.             }
  420.             else
  421.             {
  422.                 head = head.Next;
  423.                 head.Previous = default(Node);
  424.             }
  425.  
  426.             count--;
  427.         }
  428.  
  429.         /// <summary>
  430.         /// Removes the last occurrency of an element.
  431.         /// </summary>
  432.         /// <param name="elementToRemove">The element you want to remove.</param>
  433.         public void RemoveLast(TType elementToRemove)
  434.         {
  435.             if (count == 0)
  436.             {
  437.                 throw new InvalidOperationException("The list is empty!!! Try adding something first!!!");
  438.             }
  439.  
  440.             Node currNode = tail;
  441.             if (!currNode.Value.Equals(elementToRemove))
  442.             {
  443.                 try
  444.                 {
  445.                     while (!currNode.Previous.Value.Equals(elementToRemove))
  446.                     {
  447.                         currNode = currNode.Previous;
  448.                     }
  449.                 }
  450.                 catch (NullReferenceException)
  451.                 {
  452.                     throw new InvalidOperationException("No such element excists!!!");
  453.                 }
  454.  
  455.                 try
  456.                 {
  457.                     Node nextNode = currNode;
  458.                     Node prevNode = currNode.Previous.Previous;
  459.                     nextNode.Previous = prevNode;
  460.                     prevNode.Next = nextNode;
  461.                 }
  462.                 catch (NullReferenceException)
  463.                 {
  464.                     head = head.Next;
  465.                     head.Previous = default(Node);
  466.                 }
  467.             }
  468.             else
  469.             {
  470.                 tail = tail.Previous;
  471.                 tail.Next = default(Node);
  472.             }
  473.  
  474.             count--;
  475.         }
  476.  
  477.         /// <summary>
  478.         /// Removes all elements you want.
  479.         /// The operation starts from the beginning of the list.
  480.         /// </summary>
  481.         /// <param name="elementToRemove">The elements you want to remove.</param>
  482.         public void RemoveAll(TType elementToRemove)
  483.         {
  484.             if (count == 0)
  485.             {
  486.                 throw new InvalidOperationException("The list is empty!!! Try adding something first!!!");
  487.             }
  488.  
  489.             bool allElementsAreRemoved = false;
  490.             while (!allElementsAreRemoved)
  491.             {
  492.                 try
  493.                 {
  494.                     RemoveFirst(elementToRemove);
  495.                 }
  496.                 catch (InvalidOperationException)
  497.                 {
  498.                     allElementsAreRemoved = true;
  499.                 }
  500.             }
  501.         }
  502.  
  503.         /// <summary>
  504.         /// Removes an element at the entered index.
  505.         /// </summary>
  506.         /// <param name="indexToRemoveAt">The index of the element you want to remove.</param>
  507.         public void RemoveAt(int indexToRemoveAt)
  508.         {
  509.             if (count == 0)
  510.             {
  511.                 throw new InvalidOperationException("The list is empty!!! Try adding something first!!!");
  512.             }
  513.  
  514.             if (indexToRemoveAt == 0)
  515.             {
  516.                 head = head.Next;
  517.                 head.Previous = default(Node);
  518.             }
  519.             else if ((indexToRemoveAt + 1) == count)
  520.             {
  521.                 tail = tail.Previous;
  522.                 tail.Next = default(Node);
  523.             }
  524.             else
  525.             {
  526.                 Node currNode = head;
  527.                 int currIndex = 0;
  528.                 while (currIndex != indexToRemoveAt)
  529.                 {
  530.                     currNode = currNode.Next;
  531.                     currIndex++;
  532.                 }
  533.  
  534.                 Node prevNode = currNode.Previous;
  535.                 Node nextNode = currNode.Next;
  536.  
  537.                 prevNode.Next = nextNode;
  538.                 nextNode.Previous = prevNode;
  539.             }
  540.  
  541.             count--;
  542.         }
  543.  
  544.         /// <summary>
  545.         /// Searches the element at the entered index.
  546.         /// </summary>
  547.         /// <param name="indexToGetFrom">The index of the element you want to get.</param>
  548.         /// <returns>Returns the element from the entered index in the collection.</returns>
  549.         public TType GetElementByIndex(int indexToGetFrom)
  550.         {
  551.             if (indexToGetFrom < 0 || indexToGetFrom >= count)
  552.             {
  553.                 throw new InvalidOperationException("The index is outside the bounds of the list!!!");
  554.             }
  555.  
  556.             TType elementToReturn = default(TType);
  557.  
  558.             if (indexToGetFrom == 0)
  559.             {
  560.                 elementToReturn = head.Value;
  561.             }
  562.             else if (indexToGetFrom + 1 == count)
  563.             {
  564.                 elementToReturn = tail.Value;
  565.             }
  566.             else
  567.             {
  568.                 Node currNode = head.Next;
  569.                 int currIndex = 1;
  570.                 while (currIndex != indexToGetFrom)
  571.                 {
  572.                     currNode = currNode.Next;
  573.  
  574.                     currIndex++;
  575.                 }
  576.  
  577.                 elementToReturn = currNode.Value;
  578.             }
  579.  
  580.             return elementToReturn;
  581.         }
  582.        
  583.         /// <summary>
  584.         /// Returns the index of the first occurrency of the element you want.
  585.         /// </summary>
  586.         /// <param name="elementToCheck">Enter the element which index you want to know.</param>
  587.         /// <returns>Returns the index of the element you want.</returns>
  588.         public int GetIndex(TType elementToCheck)
  589.         {
  590.             if (!Contains(elementToCheck))
  591.             {
  592.                 throw new InvalidOperationException("No such element excists in the list!!!");
  593.             }
  594.  
  595.             int indexOfElement = 0;
  596.             Node currNode = head;
  597.             while (!currNode.Equals(tail) && !currNode.Value.Equals(elementToCheck))
  598.             {
  599.                 currNode = currNode.Next;
  600.  
  601.                 indexOfElement++;
  602.             }
  603.  
  604.             return indexOfElement;
  605.         }
  606.  
  607.         /// <summary>
  608.         /// Transfers the elements from the list to an array.
  609.         /// </summary>
  610.         /// <returns>An array collection with all elements from the list.</returns>
  611.         public TType[] ToArray()
  612.         {
  613.             TType[] arrayToReturn = new TType[count];
  614.  
  615.             for (int currElement = 0; currElement < count; currElement++)
  616.             {
  617.                 arrayToReturn[currElement] = GetElementByIndex(currElement);
  618.             }
  619.  
  620.             return arrayToReturn;
  621.         }
  622.  
  623.         /// <summary>
  624.         /// Joins the data in the following way [1, 2, 3...n-1]
  625.         /// </summary>
  626.         /// <returns>Returns all elements separated by a comma.</returns>
  627.         public override string ToString()
  628.         {
  629.             return string.Join(", ", ToArray());
  630.         }
  631.     }
  632. }
Advertisement
Add Comment
Please, Sign In to add comment