資料結構在程式設計世界中一直是非常重要的一環,不管是開發還是演算法,哪怕是單純為了面試,資料結構都是必修課,今天我們介紹連結串列中的一種——雙向連結串列的程式碼實現。
好了,話不多說直接上程式碼。
雙向連結串列
首先,我們定義一個節點類: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)
就可以例項化一個節點啦。
接下來我們來定義連結串列類:
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,我們預設在指定下標的後面插入新節點。
在這裡我們同樣要特殊考慮頭節點和尾結點的情況。
在執行插入時先將新節點的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)
執行上面的操作,檢查一下你的輸出吧,如果你有任何建議歡迎留言告訴我