zoukankan      html  css  js  c++  java
  • 数据结构与算法-单向链表

    概述


    由于最近在工作中需要用到树形结构来解决一些问题,所以萌生了系统学习“数据结构和算法”的想法,于是乎从最简单的表结构开始。由于数组是最简单的表结构的实现,也是各个编程语言内置的数据类型,所以不做更多的记录。表结构中以下实现打算学习:

    • LinkedList
    • Stack
    • Queue
    • HashTable
    • Dictionary

    本篇为学习数据结构的第一篇随笔,从最简单的单向链表开始吧。

    实现(C#)


    平台:dotNet Core 1.0, C#

    IDE:VSCode

    如果考虑算法复用的话,可以实现泛型。

      1 public class SingleLinkedList
      2     {
      3         //Inner class, represents a node of linked list. Each node consists of data and a link to next node
      4         class Node
      5         {
      6             public Node() { }
      7             public Node(object item)
      8             {
      9                 Data = item;
     10                 Next = null;
     11             }
     12             public object Data { get; set; }
     13             public Node Next { get; set; }
     14 
     15             public override string ToString()
     16             {
     17                 return "Node:" + Data.ToString();
     18             }
     19         }
     20 
     21         public SingleLinkedList()
     22         {
     23             header = null;
     24         }
     25 
     26         #region Public API
     27 
     28         //Add item before first node
     29         public void AddFirst(object item)
     30         {
     31             if (header == null)
     32             {
     33                 header = new Node(item);
     34             }
     35             else
     36             {
     37                 var newNode = new Node(item);
     38                 newNode.Next = header;
     39                 header = newNode;
     40             }
     41         }
     42 
     43         //Add item after last node
     44         public void AddLast(object item)
     45         {
     46             if (header == null)
     47             {
     48                 header = new Node(item);
     49             }
     50             else
     51             {
     52                 LastNode().Next = new Node(item);
     53             }
     54         }
     55 
     56         public void Insert(int index, object item)
     57         {
     58             if (index < 0) throw new ArgumentOutOfRangeException();
     59             if (index == 0)
     60             {
     61                 AddFirst(item);
     62                 return;
     63             }
     64             if (header == null) throw new ArgumentOutOfRangeException();
     65 
     66             var node = GetNode(index - 1);
     67             var newNode = new Node(item);
     68             newNode.Next = node.Next;
     69             node.Next = newNode;
     70         }
     71 
     72         public object Get(int index)
     73         {
     74             return GetNode(index).Data;
     75         }
     76 
     77         //Find index of specified data
     78         public int IndexOf(object item)
     79         {
     80             if (header == null) return -1;
     81 
     82             var curIndex = 0;
     83             for (var cur = new Node { Next = header }; cur.Next != null; cur = cur.Next, curIndex++)
     84             {
     85                 if (!cur.Next.Data.Equals(item)) continue;
     86                 return curIndex;
     87             }
     88 
     89             return -1;
     90         }
     91 
     92         //Remove specified data of its first occurance
     93         public void Remove(object item)
     94         {
     95             if (header == null) return;
     96 
     97             //Add a fake node pointing to header, so we don't need set up a local variable pointing to header. This is simple. Nice trick.
     98             for (var cur = new Node { Next = header }; cur.Next != null; cur = cur.Next)
     99             {
    100                 if (!cur.Next.Data.Equals(item)) continue;
    101                 if (cur.Next == header)
    102                 {
    103                     header = header.Next;
    104                 }
    105                 else
    106                 {
    107                     cur.Next = cur.Next.Next;
    108                 }
    109             }
    110         }
    111 
    112         //此方法可以理解为先获取index-1位置的Node,然后设置此Node的下一个节点跳过index处的节点
    113         public void RemoveAt(int index)
    114         {
    115             if (index < 0 || header == null) throw new ArgumentOutOfRangeException();
    116             else if (index == 0)
    117             {
    118                 header = header.Next;
    119             }
    120             else
    121             {
    122                 Node pre = GetNode(index - 1);
    123                 pre.Next = pre.Next.Next;
    124             }
    125         }
    126 
    127         public bool Contains(object item)
    128         {
    129             if (header == null) return false;
    130             var current = header;
    131             while (current != null && !current.Data.Equals(item))
    132             {
    133                 current = current.Next;
    134             }
    135             return current != null;
    136         }
    137 
    138         public void Clear()
    139         {
    140             header = null;
    141         }
    142 
    143         public bool IsEmpty()
    144         {
    145             return header == null;
    146         }
    147 
    148         public int Count()
    149         {
    150             if (IsEmpty()) return 0;
    151             int count = 1;
    152             for (var cur = header; cur.Next != null; cur = cur.Next, count++)
    153             {
    154             }
    155             return count;
    156         }
    157 
    158         public override string ToString()
    159         {
    160             if (header == null) return "Empty";
    161             StringBuilder sb = new StringBuilder();
    162             for (Node current = header; current != null; current = current.Next)
    163             {
    164                 sb.Append(current.Data.ToString());
    165                 if (current.Next != null) sb.Append("->");
    166             }
    167             return sb.ToString();
    168         }
    169 
    170         #endregion
    171 
    172         #region Private Method
    173 
    174         private Node LastNode()
    175         {
    176             if (header == null) throw new InvalidOperationException();
    177 
    178             var current = header;
    179             while (current.Next != null)
    180             {
    181                 current = current.Next;
    182             }
    183             return current;
    184         }
    185 
    186         private Node GetNode(int index)
    187         {
    188             if (header == null) throw new ArgumentOutOfRangeException();
    189 
    190             int curIndex = 0;
    191             var cur = header;
    192             while (cur != null && curIndex != index)
    193             {
    194                 cur = cur.Next;
    195                 curIndex++;
    196             }
    197 
    198             if (cur == null)
    199             {
    200                 throw new ArgumentOutOfRangeException();
    201             }
    202             else
    203             {
    204                 return cur;
    205             }
    206         }
    207 
    208 
    209         #endregion
    210 
    211         #region Fields
    212 
    213         private Node header;
    214 
    215         #endregion
    216     }

     

    测试代码


     1 public static void Main(string[] args)
     2         {
     3             Can_Add_First();
     4             Can_Add_Last();
     5             Can_Insert();
     6             Other();
     7 
     8             Console.ReadKey();
     9         }
    10 
    11         static void Can_Add_First()
    12         {
    13             var list = new SingleLinkedList();
    14             //add when list is empty
    15             list.AddFirst("First");
    16             Expect(list, "First");
    17             //add when list is not empty
    18             list.AddFirst("Second");
    19             list.AddFirst("Third");
    20             Expect(list, "Third->Second->First");
    21         }
    22 
    23         static void Can_Add_Last()
    24         {
    25             var list = new SingleLinkedList();
    26             //add when list is empty
    27             list.AddLast("First");
    28             Expect(list, "First");
    29             //add when list is not empty
    30             list.AddLast("Second");
    31             list.AddLast("Third");
    32             Expect(list, "First->Second->Third");
    33         }
    34 
    35         static void Can_Insert()
    36         {
    37             var list = new SingleLinkedList();
    38             //insert when list is empty
    39             list.Insert(0, "First");
    40             Expect(list, "First");
    41             //insert when list is not empty
    42             list.Insert(1, "Second");
    43             Expect(list, "First->Second");
    44             list.Insert(1, "Third");
    45             Expect(list, "First->Third->Second");
    46             list.Insert(0, "Forth");
    47             Expect(list, "Forth->First->Third->Second");
    48         }
    49 
    50         static void Other()
    51         {
    52             var list = new SingleLinkedList();
    53             list.AddLast("First");
    54             list.AddLast("Second");
    55             list.AddLast("Third");
    56             Console.WriteLine("object Get(int) Passed: " + (list.Get(1) as string == "Second"));
    57             
    58             Console.WriteLine("int IndexOf(object) Passsed: " + ((int)list.IndexOf("Third") == 2));
    59             Console.WriteLine("int IndexOf(object) Passsed: " + ((int)list.IndexOf("Forth") == -1));
    60             
    61             list.Remove("First");
    62             Expect(list, "Second->Third");
    63             list.RemoveAt(1);
    64             Expect(list, "Second");
    65             
    66             Console.WriteLine("bool Contains(object) Passed: " + (list.Contains("Second") == true));
    67             Console.WriteLine("bool Contains(object) Passed: " + (list.Contains("First") == false));
    68             Console.WriteLine("int Count() Passed: " + (list.Count() == 1));
    69             Console.WriteLine("bool IsEmpty() Passed: " + (list.IsEmpty() == false));
    70             
    71             list.Clear();
    72             Console.WriteLine("int Count() Passed: " + (list.Count() == 0));
    73             Console.WriteLine("bool IsEmpty() Passed: " + (list.IsEmpty() == true));
    74         }
  • 相关阅读:
    Python3安装后无法使用退格键
    Python之汉诺塔递归运算
    Windows开机自动执行bat脚本
    [转]java设计模式
    java享元模式
    java外观模式
    java代理模式
    java装饰者模式
    java原型模式
    java建造者模式
  • 原文地址:https://www.cnblogs.com/junejs/p/5662090.html
Copyright © 2011-2022 走看看