无法将整个双链表元素打印到控制台

时间:2019-07-14 14:01:55

标签: swift linked-list doubly-linked-list

我在Swift中实现了一个双向链表。一切都很好。链接设置良好,我可以使用nextNode和previousNode属性访问每个元素。但是,当我将列表打印到控制台时,它只是打印出列表的开头。

import Foundation

struct DoublyLinkedList<DataItem> {
    fileprivate var head : Node<DataItem>?
    fileprivate var tail : Node<DataItem>?

    var isEmpty : Bool {
        return head == nil
    }

    //to add at the beginning
    mutating func InsertAtBeginning(_ dataItem : DataItem) {
        let node = Node(dataItem: dataItem, nextNode: head, previousNode: nil)
        head?.previousNode = node
        head = node
        if tail == nil {
            tail = head
        }
    }

    //to add at the end
    mutating func insertAtEnd(_ dataItem : DataItem) {
        guard !isEmpty else {
            InsertAtBeginning(dataItem)
            return
        }

        let newNode = Node(dataItem: dataItem, nextNode: nil, previousNode: tail)
        tail?.nextNode = newNode
        //newNode.previousNode = tail
        tail = newNode

    }
}

extension DoublyLinkedList : CustomStringConvertible {
    var description : String {
        guard let doublyLinkedListHead = head else { return "UnderFlow"}
        return String(describing: doublyLinkedListHead)
    }
}

class Node<DataItem> {
    var dataItem : DataItem
    var nextNode : Node?
    var previousNode : Node?

    init(dataItem : DataItem , nextNode : Node? = nil , previousNode : Node? = nil) {
        self.dataItem = dataItem
        self.nextNode = nextNode
        self.previousNode = previousNode
    }
}

extension Node : CustomStringConvertible {
    var description: String {
        return "\(dataItem) "
    }
}

var list = DoublyLinkedList<Int>()
list.InsertAtBeginning(4)
list.InsertAtBeginning(7)
print(list)
list.insertAtEnd(5)
list.insertAtEnd(4)
print(list)
let node1 = list.head?.nextNode
node1?.previousNode
list.tail?.previousNode?.previousNode

当我打印node时,它应该打印{{1}中的node和一个nextNode和一个previousNode,而当我打印{{1 }},它应该打印整个列表。例如,当我访问node时,它应该返回list。当我打印head时,它应该包含所有元素。

2 个答案:

答案 0 :(得分:1)

这是符合您要求的实现。

现在description

Node返回previousNode!.dataItem <-> dataItem <-> nextNode!dataItem。如果previousNodenextNodenil,则将打印nil

description

DoublyLinkedList将使用linkedDescription中的Node提供列表的递归描述。每个Node的{​​{1}}将包含linkedDescriptionNode加上dataItem的{​​{1}}(如果不是{{1} }。节点之间使用linkedDescription表示链接。

nextNode

当您nil时,它将递归提供整个列表。当您<->时,它将提供extension DoublyLinkedList : CustomStringConvertible { var description : String { guard let doublyLinkedListHead = head else { return "UnderFlow"} return doublyLinkedListHead.linkedDescription } } extension Node : CustomStringConvertible { var description: String { return ((previousNode == nil) ? "nil" : "\(previousNode!.dataItem)") + " <-> \(dataItem) <-> " + ((nextNode == nil) ? "nil" : "\(nextNode!.dataItem)") } var linkedDescription: String { return "\(dataItem)" + ((nextNode == nil) ? "" : " <-> \(nextNode!.linkedDescription)") } }


示例:

print(list)
print(node)
previousNode!.dataItem <-> dataItem <-> nextNode!.dataItem
var list = DoublyLinkedList<Int>()
list.InsertAtBeginning(4)
list.InsertAtBeginning(7)
print(list)
7 <-> 4
print(list.head!)
nil <-> 7 <-> 4
list.insertAtEnd(5)
list.insertAtEnd(4)
print(list)

答案 1 :(得分:0)

// Here is the full implementation of doubly-linked-list. updates will be appreciated. 



import Foundation

struct DoublyLinkedList<DataItem> {

    fileprivate var head : Node<DataItem>?
    fileprivate var tail : Node<DataItem>?
    var isEmpty : Bool {
        return head == nil
    }

    //to add at the beginning
    mutating func InsertAtBeginning(_ dataItem : DataItem) {
        let node = Node(dataItem: dataItem, nextNode: head, previousNode: nil)
        head?.previousNode = node
        head = node
        if tail == nil {
            tail = head
        }
    }

    //to add at the end
    mutating func insertAtEnd(_ dataItem : DataItem) {
        guard !isEmpty else {
            InsertAtBeginning(dataItem)
            return
        }

        let newNode = Node(dataItem: dataItem, nextNode: nil, previousNode: tail)
        tail?.nextNode = newNode
        //newNode.previousNode = tail
        tail = newNode

    }

    //to insert at particular node
    func insertParticularly(_ dataItem : DataItem , afterNode : Node<DataItem>) {
        let node = Node(dataItem: dataItem)
        afterNode.nextNode?.previousNode = node
        node.nextNode = afterNode.nextNode
        afterNode.nextNode = node
        node.previousNode = afterNode


    }

    //to find a node at particular index
    func findNode(at index : Int) -> Node<DataItem>? {
        var currentIndex = 0
        var currentNode =  head
        while currentNode != nil && currentIndex < index {
            currentNode = currentNode?.nextNode
            currentIndex += 1
        }
        return currentNode
    }

    //MARK:- remove functionality

    //remove the first element
    mutating func removeFirst() -> DataItem? {

        defer {
            head = head?.nextNode
            if isEmpty {
                head = nil
            }
        }

        return head?.dataItem
    }

    // remove the last element
    mutating func removeLast() -> DataItem? {


        guard let headValue = head else {
            return nil
        }

        guard headValue.nextNode != nil else {
            return removeFirst()
        }

        var previous = headValue
        var current = headValue

        while let next = current.nextNode {
            previous = current
            current = next
        }

        previous.nextNode = nil
        tail = previous
        return current.dataItem

    }

    // remove from a specific location
    mutating func removeAt(at node : Node<DataItem>?) -> DataItem? {
        defer {
            if node === tail {
                removeLast()
            }
            node?.previousNode?.nextNode = node?.nextNode
            node?.nextNode?.previousNode = node?.previousNode
        }
        return node?.nextNode?.dataItem
    }

}

extension DoublyLinkedList : CustomStringConvertible {

    var description : String {
        guard let doublyLinkedListHead = head else { return "UnderFlow"}
        //return String(describing: doublyLinkedListHead)
        return doublyLinkedListHead.linkedDescription
    }

}

class Node<DataItem> {
    var dataItem : DataItem
    var nextNode : Node?
    var previousNode : Node?



    init(dataItem : DataItem , nextNode : Node? = nil , previousNode : Node? = nil) {
        self.dataItem = dataItem
        self.nextNode = nextNode
        self.previousNode = previousNode
    }
}

extension Node : CustomStringConvertible {

    var description: String {
        return ((previousNode == nil) ? "nil" : "\(previousNode!.dataItem)") +
                " <-> \(dataItem) <-> " +
            ((nextNode == nil) ? "nil" : "\(nextNode!.dataItem)")
    }
        var linkedDescription: String {
            return "\(dataItem)" + ((nextNode == nil) ? "" : " <-> \(nextNode!.linkedDescription)")

        }

}


var list = DoublyLinkedList<Int>()
list.InsertAtBeginning(4)
list.insertAtEnd(5)
list.insertAtEnd(4)
list.insertAtEnd(7)
list.insertAtEnd(2)
list.insertAtEnd(0)

list.description
let node1 = list.findNode(at: 3)
node1?.previousNode
list.head