前言
推薦個網站,學習數據結構時可以到 visualgo這個網站,感受認識操作一些數據結構的整個動態執行過程,當我們在用代碼實現其數據結構的時候,它能給我們帶來一些code的思路
棧
棧(stack),它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。
棧允許進行插入和刪除操作的一端稱爲棧頂(top),另一端爲棧底(bottom);棧底固定,而棧頂浮動;棧中元素個數爲零時稱爲空棧。插入一般稱爲進棧(PUSH),刪除則稱爲退棧(POP)。
python代碼實現
class Stack(object):
def __init__(self,limit = 10):
self.stack = []
self.limit = limit
def push(self,data):
if len(self.stack) >= self.limit:
raise IndexError("超出棧頂容量")
#List append往左加元素
self.stack.append(data)
def pop(self):
if self.stack:
return self.stack.pop()
else:
raise IndexError("已經空棧")
def peek(self):
if self.stack:
return self.stack[-1]
def is_empty(self):
#bool()若沒有參數,返回False,判斷棧是否爲空
return not bool(self.stack)
def size(self):
#查看棧中有幾個元素
return len(self.stack)
#以上即是實現一個棧的基本代碼
#作業(用棧解決括號匹配問題)
"""算法思路,循環字符串的每一個字符("("或")"),如果是(,直接入棧
如果是")",先判斷棧爲不爲空,若爲空,返回括號匹配錯誤,若不爲空,
棧pop出一個元素,字符串的字符循環完之後,再判斷棧爲不爲空,若不爲空,
返回括號匹配錯誤,若不爲空,返回括號匹配正確
"""
def balanced_parentheses(str):
stack = Stack(len(str))
for char in str:
if char == "(":
stack.push(char)
elif char == ")":
if stack.size() == 0:
return False
stack.pop()
return stack.is_empty()
if __name__ == "__main__":
examples = ["(())","())","(()))"]
for example in examples:
print(balanced_parentheses(example))
單鏈表
鏈表(linked_list)是物理存儲單元上非連續的、非順序的存儲結構,數據元素的邏輯順序是通過鏈表的指針地址實現,每個元素包含兩個結點,一個是存儲元素的數據域 (內存空間),另一個是指向下一個結點地址的指針域。根據指針的指向,鏈表能形成不同的結構,例如單鏈表,雙向鏈表,循環鏈表等。而單鏈表中的每個節點只包含一個數據域和一個指針域(尾)。
想獲取對鏈表的更多認識可戳這篇文章數據結構中的鏈表,你知道多少?
python代碼實現
class Node:
#初始化鏈點
def __init__(self,data):
self.data = data
self.next = None
class Link_List:
#初始化鏈表,注意初始化鏈表時head可能不存在
def __init__(self,head = None):
self.head = head
#鏈表的添加功能
def append(self,new_element):
#current當前的
current = self.head
#當頭部節點存在
if self.head:
while current.next:
current = current.next
current.next = new_element
#當頭部節點不存在
else:
self.head = new_element
def is_empty(self):
#判斷鏈表爲不爲空,只需要判斷head爲不爲空
return not self.head
def get_length(self):
#求鏈表的長度
temp =self.head
length = 0
while temp != None:
length = length + 1
temp = temp.next
return length
def insert(self,position,new_element):
#在鏈表指定索引處插入元素
if position < 0 or position > self.get_length():
raise IndexError("插入位置超出範圍")
temp = self.head
#當插入位置在第一位時候,把head變爲新節點
if position == 0:
new_element.next = temp
self.head = new_element
return
i = 0
while i < position:
pre = temp
temp = temp.next
i+=1
pre.next = new_element
new_element.next = temp
def remove(self,position):
#刪除指定索引的鏈表元素
if position < 0 or position > self.get_length():
raise IndexError("要刪除的鏈表元素超出範圍")
i = 0
temp = self.head
while temp != None:
if position == 0:
self.head = temp.next
temp.next = None
return
pre = temp
temp = temp.next
i+=1
if i == position:
pre.next = temp.next
temp.next = None
return
def print_list(self):
#打印鏈表元素
temp = self.head
while temp is not None:
print(temp.data)
temp = temp.next
def initlist(self,data_list):
#將列表轉爲鏈表
#創建頭結點
self.head = Node(data_list[0])
temp = self.head
#逐個爲列表中的元素創建結點
for i in data_list[1:]:
node = Node(i)
temp.next = node
temp = temp.next
def reverse(self):
#將鏈表反轉
"""
假設存在鏈表 1 → 2 → 3 → Ø,我們想要把它改成 Ø ← 1 ← 2 ← 3。
在遍歷列表時,將當前節點的 next 指針改爲指向前一個元素。
由於節點沒有引用其上一個節點,因此必須事先存儲其前一個元素。
在更改引用之前,還需要另一個指針來存儲下一個節點。不要忘記在最後返回新的頭引用!
"""
prev = None
current = self.head
while current:
next_node = current.next
current.next = prev #遍歷每一個結點,使其next指向前一個結點
prev = current
current = next_node
self.head = prev
#交換兩個數據特定的鏈表元素
def swapNodes(self,node1,node2):
#傳入的node1和node2是要交換的鏈表元素的數據,而不是鏈表元素
prevD1 = None
prevD2 = None
#先判斷要實行元素交換的鏈表是否爲空,空退出
if self.is_empty():
return
else:
#判斷要交換的元素數據是否相同,相同退出
if node1 == node2:
return
else:
#根據node1和node2的值找出要交換的兩個鏈表元素
D1 = self.head
while D1 != None and D1.data != node1:
prevD1 = D1
D1 = D1.next
D2 = self.head
while D2 != None and D2.data != node2:
prevD2 = D2
D2 = D2.next
#如果要交換的D1節點是head,做如下交換
if prevD1 != None:
prevD1.next = D2
else:
self.head = D2
#如果要交換的D2節點是head,做如下交換
if prevD2 != None:
prevD2.next = D1
else:
self.head = D1
#如果要交換的D1和D2均不是head,做如下交換
temp = D1.next
D1.next = D2.next
D2.next = temp
if __name__ == "__main__":
link_list = Link_List()
link_list.append(Node(5))
link_list.append(Node(4))
link_list.append(Node(3))
link_list.append(Node(2))
link_list.append(Node(1))
print("交換前")
link_list.print_list()
link_list.swapNodes(1,4)
print("交換後")
link_list.print_list()
雙鏈表
雙向鏈表(Double_linked_list)也叫雙鏈表,是鏈表的一種,它的每個數據結點中都有兩個指針,分別指向它的前一個結點和他的後一個結點。所以,從雙向鏈表中的任意一個結點開始,都可以很方便地訪問它的前驅結點和後繼結點。
python代碼實現
class Node():
def __init__(self,data):
#雙鏈表對比單鏈表,其中的元素多了一個頭指針(prev)
self.data = data
self.next = None
self.prev = None
class DLinkList():
"""雙鏈表它不是循環鏈表"""
def __init__(self):
self._head = None
#判斷鏈表是否爲空
def is_empty(self):
return not self._head
#獲取鏈表長度
def get_length(self):
count = 0
current = self._head
while current:
count += 1
current = current.next
return count
#打印鏈表中的元素
def print_node(self):
current = self._head
while current != None:
print(current.data)
current = current.next
print("到盡頭了")
#鏈表頭部添加元素
def add(self,data):
new_node = Node(data)
if self.is_empty():
self._head = new_node
else:
new_node.next = self._head
self._head.prev = new_node
self._head = new_node
#鏈表尾部插入數據
def append(self,data):
new_node = Node(data)
#循環找到鏈表尾部元素
current = self._head
while current != None:
current = current.next
current.next = new_node
new_node.prev = current
#查詢特定數據的鏈表元素是否存在
def search(self,data):
current = self._head
while current != None:
if current.data == data:
return True
current = current.next
return False
#往特定位置插入鏈表元素
def insert(self,position,data):
#如果position <= 0,均往鏈表首插入
if position <= 0:
self.add(data)
#如果position >= 鏈表長度,均往鏈表尾插入
elif position >= self.get_length:
self.append(data)
#如果position既不 <= 0和 >= 0,則循環找到position-1的元素,讓其尾指針
#指向插入的元素,讓其下一個節點頭指針指向插入的元素,而插入的元素的頭指針
#指向位置position-1的元素,尾指針指向指向position-1的元素的下一個元素
else:
new_node = Node(data)
current = self._head
count = 0
while count < (position-1):
count += 1
current = current.next
new_node.prev = current
new_node.next = current.next
current.next = new_node
current.next.prev = new_node
def remove(self,data):
#刪除指定數據的鏈表元素
#如果鏈表爲空則刪除錯誤
if self.is_empty:
return
else:
current = self._head
if current.data == data:
if current.next == None:
self._head = None
else:
current.next.prev = None
self._head = current.next
return
while current != None:
current = current.next
if current.data == data:
current.prev.next = current.next
current.next.prev = current.prev
break