數據結構-雙向鏈表(Python實現)

數據結構在編程世界中一直是很是重要的一環,無論是開發仍是算法,哪怕是單純爲了面試,數據結構都是必修課,今天咱們介紹鏈表中的一種——雙向鏈表的代碼實現。node

好了,話很少說直接上代碼。面試

雙向鏈表

首先,咱們定義一個節點類:Node算法

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None
        self.prev = None
    def getData(self):
        return self.data

    def setData(self, data):
        self.data = data

    def getNext(self):
        return self.next

    def getPrev(self):
        return self.prev

好,咱們定義了節點類,並實現了獲取、修改節點數據、獲取上一個/下一個節點的方法。編程

經過node = Node(10)就能夠實例化一個節點啦。數據結構

接下來咱們來定義鏈表類:app

class TwoWayList:
    def __init__(self):
        self.head = None
        self.tail = None
        self.length = 0

好,咱們定義了一個鏈表類,並設置三個屬性,head表示頭節點,tail表示尾節點,length表示鏈表長度,接下來,咱們給鏈表類添加一些方法。函數

  • 判斷鏈表是否爲空:
def isEmpty(self):
        return self.head == None
  • 在鏈表尾部添加節點:
def append(self, item):
        if self.length == 0:
            node = Node(item)
            self.head = node
            self.tail = node
            self.length = 1
            return
        node = Node(item)
        tail = self.tail
        tail.next = node
        node.prev = tail
        self.tail = node
        self.length += 1

添加節點的時候,咱們首先要判斷鏈表是否爲空,另外要注意給本來的尾節點設置next屬性,新的尾節點設置prev屬性,更新鏈表的tail和length屬性。測試

  • 鏈表中插入節點:
def insert(self, index, item):
        length = self.length
        if (index<0 and abs(index)>length) or (index>0 and index>=length):
            return False
        if index < 0:
            index = index + length
        if index == 0:
            node = Node(item)
            if self.head != None:
                self.head.prev = node
            else:
                self.tail = node
            node.next = self.head
            self.head = node
            self.length += 1
            return True
        if index == length - 1:
            return self.append(item)


        node1 = self.head
        for i in range(0, index):
            node1 = node1.next
        node2 = node1.next

        node = Node(item)
        node.prex = node1
        node.next = node2
        node1.next = node
        node2.prev = node

        self.length += 1
        return True

插入節點時候,咱們參數爲下標index和數據item,咱們默認在指定下標的後面插入新節點。code

在這裏咱們一樣要特殊考慮頭節點和尾結點的狀況。開發

在執行插入時先將新節點的next、prev屬性指向相應節點,在將先後節點的next和prev指向新節點,同時注意更新鏈表的length屬性。

  • 根據節點數據獲取鏈表上的節點
def get(self, data):
        node = self.head
        for i in range(self.length):
            if node.data == data:
                return node
            else:
                node = node.next
        else:
            return False
  • 根據下標獲取鏈表上的節點
def getByIndex(self, index):
        if index >= self.length:
            return False
        if index == 0:
            return self.head

        now = self.head
        for i in range(self.length):
            if i == index:
                return now
            now = now.next
  • 更新指定下標節點的數據
def setData(self, index, data):
        if index >= self.length:
            return False
        if index == 0:
            self.head.data = data

        now = self.head
        for i in range(self.length):
            if i == index:
                now.data = data
                return True
            now = now.next
  • 刪除指定下標的節點
def remove(self, index):
        if index >= self.length:
            return False
        if index == 0:
            self.head = self.head.next
            if self.length != 1:
                self.head.prev = None
            self.length -= 1
            return True
        if index == self.length-1:
            self.tail = self.tail.prev
            self.tail.next = None
            self.length -= 1
            return True

        now = self.head
        for i in range(self.length):
            if i == index:
                now.next.prev = now.prev
                now.prev.next = now.next
                self.length -= 1
                return True
            now = now.next

注意要更新length屬性,若是刪除頭節點還要更新head屬性,若是刪除尾結點要更新tail屬性。

  • 鏈表翻轉
def reverse(self):
        now = self.head
        last = None
        for i in range(self.length):
            last = now
            now = now.next
            tmp = last.prev
            last.prev = last.next
            last.next = tmp
        tmp = self.head
        self.head = self.tail
        self.tail = tmp
        return True

鏈表翻轉咱們不光要更新tail和head屬性,還要將每個節點上的next和prev屬性調換。

  • 清空鏈表
def clear(self):
        self.head = None
        self.tail = None
        self.length = 0
  • 實現鏈表類的__str__方法,定義print()函數打印鏈表的方式
def __str__(self):
        string = ''
        node = self.head
        for i in range(self.length):
            string += str(node.data) + '/'
            node = node.next
        return string

這裏咱們讓print()函數打印鏈表時,從頭節點開始依次打印每一個節點的數據,並用/符號分割。

好啦,一個雙向鏈表咱們就定義好了,並實現了一些操做鏈表的方法,咱們了來測試一下咱們定義的鏈表吧~

li = TwoWayList()
li.isEmpty()
li.insert(0, 1)
li.getByIndex(0)
li.remove(0)

print(li)
li.append(1)

print(li)
li.append(2)
print(li)
li.append(4)
print(li)
li.insert(2,3)
print(li)
li.insert(3,4)

print(li)
li.remove(2)
print(li)
li.setData(2,10)
print(li)
li.reverse()
print(li)
print(li.get(2).data)
print(li.getByIndex(1).data)

執行上面的操做,檢查一下你的輸出吧,若是你有任何建議歡迎留言告訴我

相關文章
相關標籤/搜索