如何快速实现双向链表?

时间:2019-07-13 16:49:26

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

如何在Swift中通过插入和删除之类的所有操作实现双向链表?

我知道如何实现单链列表,但是我找不到找到使其成为双链列表的方法。我是编码的初学者。

import UIKit

struct LinkedList<Value> {

    var Head : node<Value>?
    var Tail : node<Value>?

    var isEmpty : Bool {
        return Head == nil
    }

    // to add at the beginning of the list
    mutating func push(_ value : Value) {
        Head = node(value: value, nextNode: Head)
        if Tail == nil {
            Tail = Head
        }
    }

    // to add at the end of the list
    mutating func append(_ value : Value) {
        guard !isEmpty else {
            push(value)
            return
        }

        let newNode = node(value: value)
        Tail?.nextNode = newNode
        Tail = newNode
    }

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

    // to insert at a particular location

    func insert(_ value : Value, afterNode : node<Value>) {
        afterNode.nextNode = node(value: value, nextNode: afterNode.nextNode)
    }

    mutating func pop() -> Value? {

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

        return Head?.value
    }


    mutating func removeLast() -> Value? {

        guard let head = Head else {
            return nil
        }
        guard head.nextNode != nil else {
            return pop()
        }

        var previous = head
        var current = head

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

        previous.nextNode = nil
        Tail = previous
        return current.value

    }

    mutating func remove(after node : node<Value>?) -> Value? {

        defer {
            if node === Tail {
                Tail = node
            }
            node?.nextNode = node?.nextNode?.nextNode
        }
        return node?.nextNode?.value
    }
}

extension LinkedList : CustomStringConvertible {
    var description: String {

        guard let linkedListHead = Head else {
            return "Empty List"
        }
        return String(describing: linkedListHead)
    }


}

class node<Value> {

    var value : Value
    var nextNode : node?

    init(value : Value , nextNode : node? = nil) {

        self.value = value
        self.nextNode = nextNode

    }

}


extension node : CustomStringConvertible {
    var description: String {
        guard let nextValue = nextNode else { return "\(value)" }

        return "\(value) -> " + String(describing: nextValue) + " "
    }


}

var listOfIntegers = LinkedList<Int>()
var listOfStrings = LinkedList<String>()

listOfIntegers.push(1)
listOfIntegers.push(3)
listOfIntegers.push(4)
listOfIntegers.append(6)
let nodeInfo = listOfIntegers.findNode(at: 1)!
listOfIntegers.insert(8, afterNode: nodeInfo)
print(listOfIntegers)
listOfStrings.push("hello")
listOfStrings.push("Sardar Ji!")
print(listOfStrings)
let index = 3
let node2 = listOfIntegers.findNode(at: index - 1)
listOfIntegers.remove(after: node2)
print(listOfIntegers)

我想以相同的方式实现双向链表,并且输出应如下所示:

node1 <-> node2 <-> node3

2 个答案:

答案 0 :(得分:0)

//here is the full implementaion of doubly-linked-list in swift. 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

答案 1 :(得分:0)

从根本上讲,您的问题是LinkedList中有头和尾指针,但是node仅具有nextNode指针。如果node是表示列表中每个项目的结构,并且如果您希望能够在任一方向上遍历列表,则每个项目都需要指向下一个项目以及上一个项目的链接。这就是为什么他们称其为“双重链接列表”。

  1. 为您的previousNode结构添加一个node指针。
  2. 在代码中查找修改nextNode指针并更改代码以保留previousNode指针的每个位置。