当前位置:  开发笔记 > 编程语言 > 正文

我是否完成了此链接列表代码?

如何解决《我是否完成了此链接列表代码?》经验,为你挑选了1个好方法。

嗨,我正在尝试使用链接列表进行练习.

我定义了一个名为的Object类Student:

public class Student
{
      protected string  Student_Name;
      protected int Student_ID;
      protected int Student_Mark;
      protected char    Student_Grade;

      public Student()  // default Constructor
      {
         Student_Name = "           ";
         Student_ID = 0;
         Student_Mark = 0;
         Student_Grade = ' ';
        }

      public Student(string Sname, int Sid, int Smark, char Sgrade) // Constructor
      {
         int len = sname.Length;
         Student_Name = sname.Substring(0, len);
         //Student_Name = sname.Substring(0, sname.Length);
         Student_ID = Sid;
         Student_Mark = Smark;
         Student_Grade = Sgrade;
      }
}

然后是一个Node班级:

public class S_Node
{
      public Student    Element;
      public S_Node Link;

      public S_Node()
      {
         Element = new Student();
         Link = null;
      }

      public Node(Student theElement)
      {
         Element = theElement;
         Link = null;
      }
}

LinkedList:

public class S_LinkedList
{
    protected S_Node header;
    protected S_Node tail;

    public S_LinkedList()
    {
       header = new S_Node();
       Tail = new S_Node();
       header.Link = Tail;
    }

    // METHODS which i don't know how to do it (never use linkedlist before)
}

我需要使用"链表数据结构类型"来组织这些数据.

包含链接列表的所有方法作为我已经学习的向列表中添加节点 - >(插入),从列表中删除节点,如我所知 - >((删除),遍历我学到的列表 - - >((PrintList),在我学习的时候在列表中找到一个节点 - >((Find,FindPrevious)我自学的问题我试图搜索网络并从愚蠢的C#中读取更多信息是一场灾难.我做得太多了,我很难过,我不知道如何完成它.

我正在努力使用这个类来编写可执行程序并进行测试.

如果你不想帮助完成这个程序(希望不是)至少告诉我一些真实的例子或想法,毕竟我是一个自学者的极客:-)



1> Robert Pauls..:
 the head of the list.
 ( item1
   Element: student1
   Next ------------> ( item2
  )                     Element: student2
                        Next ------------> ( item3
                      )                      Element: student3
                                             Next: null
                                           )
                                           the tail of the list.

首先,为了能够编写StudentList类,您需要首先编写客户端代码.客户端代码是使用学生列表的代码.另外,不要一次只写一件东西扔掉.而是编写一大堆[测试]案例,这些案例练习了与StudentList交互所需的不同方式.写出特殊情况.但是,不要试图写一个瑞士军刀,只是因为它可以做一切.写下完成工作的最少量代码.

如何使用该类将严重决定类的构造方式.这是TDD或测试驱动设计的本质.

我能看到的最大问题是你不知道如何使用这门课程.所以我们先做.

// create a list of students and print them back out.
StudentList list = new StudentList();
list.Add( new Student("Bob", 1234, 2, 'A') );
list.Add( new Student("Mary", 2345, 4, 'C') );

foreach( Student student in list)
{
    Console.WriteLine(student.Name);
}

我将学生添加到列表中,然后将其打印出来.

我不需要我的客户端代码来查看StudentList内部.因此,StudentList隐藏了它如何实现链表.让我们来写一下StudentList的基础知识.

public class StudentList 
{
    private ListNode _firstElement; // always need to keep track of the head.

    private class ListNode
    {
        public Student Element { get; set; }
        public ListNode Next { get; set; }
    }

    public void Add(Student student) { /* TODO */ }

}

StudentList非常基础.在内部,它跟踪第一个或头部节点.显然始终需要跟踪第一个节点.

您也可能想知道为什么在StudentList中声明ListNode.会发生什么是ListNode类只能由StudentList类访问.这样做是因为StudentList不想向其内部实现提供详细信息,因为它控制对列表的所有访问.StudentList从不显示列表的实现方式.实现隐藏是一个重要的OO概念.

如果我们确实允许客户端代码直接操作列表,那么将StudentList放在第一位就没有意义了.

让我们继续并实现Add()操作.

public void Add(Student student)
{
    if (student == null)
        throw new ArgumentNullException("student");

    // create the new element
    ListNode insert = new ListNode() { Element = student };

    if( _firstElement == null )
    {
        _firstElement = insert;
        return;
    }

    ListNode current = _firstElement;
    while (current.Next != null)
    {
        current = current.Next;
    }

    current.Next = insert;
}

Add操作必须找到列表中的最后一项,然后将新的ListNode放在最后.虽然效率不是很高.它现在是O(N),随着列表变长,添加会变慢.

让我们对插入进行一点优化,然后重写Add方法.为了使Add更快,我们需要做的就是让StudentList跟踪列表中的最后一个元素.

private ListNode _lastElement;  // keep track of the last element: Adding is O(1) instead of O(n)

public void Add(Student student)
{
    if( student == null )
        throw new ArgumentNullException("student");

    // create the new element
    ListNode insert = new ListNode() { Element = student };

    if (_firstElement == null)
    {
        _firstElement = insert;
        _lastElement = insert;
        return;
    }

    // fix up Next reference
    ListNode last = _lastElement;
    last.Next = insert;
    _lastElement = insert;
}

现在,当我们添加时,我们不会迭代.我们只需要跟踪头部和尾部参考.

接下来:foreach循环.StudentList是一个集合,是我们想要枚举它并使用C#的集合foreach.C#编译器不能神奇地迭代.为了使用foreach循环我们需要为编译器提供一个枚举器来使用,即使我们编写的代码没有显式地使用枚举器.

首先,让我们重新访问我们如何迭代链表.

// don't add this to StudentList
void IterateOverList( ListNode current )
{
    while (current != null)
    {
        current = current.Next;
    }
}

好的.所以让我们挂钩C#的foreach循环并返回一个枚举器.为此,我们改变StudentList以实现IEnumerable.这有点先进,但你应该能够弄清楚发生了什么.

// StudentList now implements IEnumerable
public class StudentList : IEnumerable
{
    // previous code omitted

    #region IEnumerable Members
    public IEnumerator GetEnumerator()
    {
        ListNode current = _firstElement;

        while (current != null)
        {
            yield return current.Element;
            current = current.Next;
        }
    }
    #endregion

    #region IEnumerable Members
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    #endregion
}

您应该能够在那里发现链表迭代.不要被yield关键字抛出.所有产量正在做的是将当前学生返回到foreach循环.当它到达链表的末尾时,enumarator停止返回学生.

就是这样!代码以我们想要的方式工作.


*这绝不是实施清单的唯一方法.我选择将列表逻辑放在StudentList中并保持ListNode非常基本.但是代码只是我第一次单元测试所需要的,仅此而已.您可以进行更多优化,还有其他构建列表的方法.

展望未来:您需要做的是首先为代码需要做的事情创建[unit]测试,然后添加您需要的实现.


*fyi我也改写了学生班.来自C#persepctive的错误命名和奇怪的外壳,更不用说你提供的代码无法编译.我更喜欢_作为私有成员变量的领导者.有些人不喜欢这样,但是你是新手,所以我会留下他们,因为他们很容易被发现.

public class Student
{
    private string _name;
    private int _id;
    private int _mark;
    private char _letterGrade;

    private Student()  // hide default Constructor
    { }

    public Student(string name, int id, int mark, char letterGrade) // Constructor
    {
        if( string.IsNullOrEmpty(name) )
            throw new ArgumentNullException("name");
        if( id <= 0 )
            throw new ArgumentOutOfRangeException("id");

        _name = name;
        _id = id;
        _mark = mark;
        _letterGrade = letterGrade;
    }
    // read-only properties - compressed to 1 line for SO answer.
    public string Name { get { return _name; } }
    public int Id { get { return _id; } }
    public int Mark { get { return _mark; } }
    public char LetterGrade { get { return _letterGrade; } }
}

检查参数

注意属性,类和变量的不同外壳.

隐藏默认构造函数.为什么我要创建没有真实数据的学生?

提供一些只读属性.

这个类是不可改变的(即一旦你创建了一个学生,你就无法改变它).

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有