使用链接列表创建基本的浏览器历史记录

时间:2019-02-15 19:58:38

标签: c#

所以我正在做一个作业,我们用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。

1 个答案:

答案 0 :(得分:1)

这是一个基于您的代码的示例,尽管略有变化。

我没有跟踪我们状态的counteri,而是跟踪两个节点:head(第一个节点)和current(用户的那个节点)。现在)。我还将在current.Next节点而不是head节点插入新页面,因为这是我习惯使用链接列表的方式。

这样做可以使导航变得容易。要前进,我们只设置current = current.Next,而要后退,我们从head开始并向前移动,直到找到其Next指向current的节点。然后,将current设置到该节点。

要打印出历史记录,我们仅从head开始并继续移动Next。当我们看到Next == current时,就知道我们在当前页面上(我以另一种颜色打印该页面)。然后,我们可以继续打印Next节点以显示将来的节点,直到Nextnull

请注意,这实际上是导航历史记录,而不是浏览历史记录的完整记录,因为如果您返回然后访问新页面,则会丢失该页面从那里回来。

希望这会有所帮助:

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;
        }
    }
}

输出

![enter image description here