所以我有这本图表,我正在迭代并打印出来。
public class Books : IBookFinder
{
private Books(Books next, string book)
{
Next = next;
Book = book;
}
public Books Next { get; }
public string Book { get; }
public Books Previous(string book)
{
return new Books(this, book);
}
public static Books Create(string book)
{
return new Books(null, book);
}
public string FromLeft(Books books, int numberFromLeft)
{
for (int i = 1; i < numberFromRight; i++)
{
books = books?.Next; //Go through the books and return null if books is null.
}
return books.book; //Should probably check for null here as it crashes if the input number is out of book range (something else than 1-4)
}
public string FromRight(Books books, int numberFromRight
{
//How to implement this bad boy?
}
}
一切都很好,但我想实现一个方法FromRight,这样我就可以根据数字输入从图中的位置写出书的名称。例如,如果输入&#34; 3&#34;,它应该输出&#34;指环王&#34;。我该怎么做呢?任何提示都非常赞赏。
class Program
{
static void Main(string[] args)
{
var curr = Books
.Create("Harry Potter")
.Previous("Lord of the Rings")
.Previous("Twilight")
.Previous("Da Vinci Code");
while (curr != null)
{
if (curr.Next != null)
{
Console.Write(curr.Book + " --- ");
}
else
{
Console.WriteLine(curr.Book);
}
curr = curr.Next;
}
Console.WriteLine("Input number to pick a book");
var bookNumber = Console.ReadLine();
int n;
if (int.TryParse(bookNumber, out n)) //Checking if the input is a #
{
}
else
{
Console.WriteLine("Input was not a number!");
}
Console.WriteLine(bookNumber);
Console.ReadLine();
}
}
更新:
我设法找到了一种方法,而不必制作双重链表,即使这当然可能是解决此问题的最佳方案。
我已经创建了一个帮助函数Count(),它接受列表并计算条目:
private int Count(Books books)
{
int count = 1;
while (books.Next != null)
{
books = books.Next;
count++;
}
return count;
}
然后我使用此方法的返回值从右侧选择书籍:
public string FromRight(Books books, int numberFromRight)
{
var bookCount = Count(books); //Getting the amount of books.
for (int i = numberFromRight; i < bookCount; i++)
{
books = boos?.Next;
}
return books.Book;
}
答案 0 :(得分:2)
由于您要像链接列表一样创建它,要向后移动,您需要创建一个双向链接列表:https://en.wikipedia.org/wiki/Doubly_linked_list
您当前的代码没有上一个节点的代表。将前一个节点设置为当前节点,同时创建下一个节点,然后其迭代就像您最初那样。
迭代直到没有Next,然后打印直到没有上一个。
答案 1 :(得分:1)
单链表只能在一个方向上迭代,所以不可能倒退。
要从左侧获取第n个元素,您只需要进入下一个n
次。但要想从右边找出元素,首先需要达到目的。因此,要获得最后一个元素,您需要尽可能经常地去下一个元素。要获得倒数第二个元素,您需要转到结尾并在此之前返回元素。
您可能会看到它的位置:为了从右侧获取第n个元素,您需要在迭代链表时记住最后n个元素。这也意味着在最坏的情况下,当你从左边但是从右边获取第一个元素时,你会记住每个项目。
实现这一点并不困难,你可以使用长度为numberFromRight
的列表轻松完成这项工作,但由于你在最后插入并从头开始删除元素,所以你将一直在移动元素。所以你最好使用固定长度的队列。或者您使用带有变量指针的数组,这样可以避免任何移动。 FromRight
方法可能如下所示:
public Element FromRight(int numberFromRight)
{
// increment the offset by one, so that `0` means the last element,
// and `1` means the one before last, etc.
numberFromRight++;
// create an array with `numberFromRight` slots
Element[] arr = new Element[numberFromRight];
// add the current item to the array
arr[0] = this;
// `i` is the index where to add the next element
int i = 1 % numberFromRight;
// iterate through all elements until the very end
Element current = this;
while (current.Next != null)
{
current = current.Next;
// add the current element to the array
arr[i] = current;
// increment the index by one, overflowing back to the beginning of the array
i = (i + 1) % numberFromRight;
}
// the element at position `i` is the nth element from the right.
return arr[i];
}
(我选择在没有Books
类型的情况下实施此操作,因为您以混乱的方式混合了Books
和Customers
而我没有得到它。这适用于任意链接列表。)
如果你发现自己更频繁地访问结尾的元素,你应该考虑使用doubly linked list而不是保持指向左边元素的指针。这意味着需要维护更多的引用(稍微增加列表操作的复杂性),但会产生更好的性能(因为从末尾迭代与从头开始迭代相同)。
通常,您应始终选择适合您的访问模式的数据结构。没有任何数据结构适用于所有内容,因此了解这些差异并了解您在应用程序中真正需要的内容非常重要,这样您就可以选择。