所以我正在做一个作业,我们用c#编写基本的浏览器历史记录。要求是我们需要使用单链接列表来执行此操作。我遇到的问题是,当我想在历史记录中倒退打印时,它需要从列表的开头而不是列表的开头。 (例如,如果我有一个包含1、2、3、4的列表,然后返回,则将2、3、4和1移至将来的类别。)
public class UnderflowException : Exception
{
public UnderflowException(string s) : base(s) { }
}
public class OverflowException : Exception
{
public OverflowException(string s) : base(s) { }
}
class History
{
protected class IntListNode
{
public string Data;
public IntListNode Next;
public IntListNode(string data)
{
Data = data;
}
public IntListNode(string data, IntListNode next)
{
Next = next;
}
}
protected IntListNode first;
private int i;
public void PrintAll()
{
int j = 0;
IntListNode node = first;
Console.WriteLine("Privious things that you have viewed.");
while (node != null)
{
if (counter <= j)
{
break;
}
Console.WriteLine(node.Data);
node = node.Next;
j++;
}
Console.WriteLine("Things to go forward to.");
while (node != null)
{
Console.WriteLine(node.Data);
node = node.Next;
}
}
private int counter;
public void MoveBackwards()
{
if (counter >= 0)
{
counter = counter - 1;
}
else
{
throw new UnderflowException("underflow");
}
}
public void MoveForwards()
{
if (counter > i)
{
throw new OverflowException("overflow");
}
else
{
counter++;
}
}
public void VisitPage(string desc)
{
IntListNode n = new IntListNode(desc);
n.Next = this.first;
this.first = n;
counter++;
i = counter;
}
}
当我已经在列表中有项目并要求它向后移动时,它将采用列表中的第一个节点而不是最后一个节点。从先前的示例开始,希望它从1、2、3、4开始,使用go backs命令并具有历史记录显示1、2、3和正向显示4。
答案 0 :(得分:1)
这是一个基于您的代码的示例,尽管略有变化。
我没有跟踪我们状态的counter
和i
,而是跟踪两个节点:head
(第一个节点)和current
(用户的那个节点)。现在)。我还将在current.Next
节点而不是head
节点插入新页面,因为这是我习惯使用链接列表的方式。
这样做可以使导航变得容易。要前进,我们只设置current = current.Next
,而要后退,我们从head
开始并向前移动,直到找到其Next
指向current
的节点。然后,将current
设置到该节点。
要打印出历史记录,我们仅从head
开始并继续移动Next
。当我们看到Next == current
时,就知道我们在当前页面上(我以另一种颜色打印该页面)。然后,我们可以继续打印Next
节点以显示将来的节点,直到Next
为null
。
请注意,这实际上是导航历史记录,而不是浏览历史记录的完整记录,因为如果您返回然后访问新页面,则会丢失该页面从那里回来。
希望这会有所帮助:
class History
{
private class Node
{
public string Data { get; set; }
public Node Next { get; set; }
public Node(string data) { Data = data; }
}
private Node head;
private Node current;
public void VisitNewPage(string desc)
{
// Create a node for this page
var node = new Node(desc);
// If it's our first page, set the head
if (head == null) head = node;
// Update our current.Next pointer
if (current != null) current.Next = node;
// Set this page as our current page
current = node;
}
public void MoveBackwards()
{
// Can't move backwards from the head
if (current == head) return;
var previous = head;
// Find the node that's behind (pointing to) the current node
while (previous.Next != current)
{
previous = previous.Next;
}
// Make that node our new current
current = previous;
}
public void MoveForwards()
{
// Just move to the next node
if (current.Next != null) current = current.Next;
}
public void PrintCurrent()
{
Console.WriteLine($"You are on page: {current.Data}");
}
public void PrintHistory()
{
Console.WriteLine("\nBrowsing History");
if (head == null)
{
Console.WriteLine("[Empty]");
return;
}
var node = head;
// Print previous pages
while (node != current)
{
Console.WriteLine($" - {node.Data}");
node = node.Next;
}
// Print current page in green
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($" - {node.Data}");
Console.ResetColor();
node = node.Next;
// Print next pages
while (node != null)
{
Console.WriteLine($" - {node.Data}");
node = node.Next;
}
Console.WriteLine();
}
}
样品用量
这是一个简单的无限循环,可让您访问新站点,前进,后退并打印历史记录:
private static void Main()
{
var history = new History();
while (true)
{
Console.Write("Enter new page to visit, [b]ack, [f]orward, or [p]rint: ");
var input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input)) continue;
switch (input.ToLower())
{
case "b":
case "back":
history.MoveBackwards();
break;
case "f":
case "forward":
history.MoveForwards();
break;
case "p":
case "print":
history.PrintHistory();
break;
default:
history.VisitNewPage(input);
break;
}
}
}
输出