線性表分為順序表和鏈表。
順序表:將表中元素順序地存在一大塊連續的存儲區內。元素間的順序關系由它們的存儲順序自然決定。
鏈表:將表中元素存放在通過鏈接結構構造起來的一系列存儲塊中。
順序表
優點
定位元素訪問時間復雜度為O(1)。
缺點
加入/刪除操作代價高。(除了尾端插入和刪除時間復雜度為O(1))。如果程序中需要巨大線性表,可能造成存儲管理方面的困難。
部分操作代碼python:
#修改順序表自身,將其元素順序倒置
#算法復雜度O(n)
def reverse(self):
elems = self.elements
i, j = 0, len(elems)-1
while i < j:
elems[i], elems[j] = elems[j], elems[i]
i, j = i+1, j-1
單鏈表
每個節點里只儲存一個表元素。多鏈表暫不討論。每個節點是一個二元組,存儲著elem和next。節點之間通過節點鏈接建立起單向的順序聯系。
定義一個簡單的表節點類:
#方法的第二參數用next_是為了避免與Python標準函數next重名
class LNode:
def __init__(self, elem, next_=None):
self.elem = elem
self.next = next_
加入元素
表首加入
- 創建一個新節點q并存入數據
- 原鏈表首節點head的鏈接存入新節點的next
- 修改表頭變量,使之指向新節點
#時間復雜度O(1)
q = LNode(13) //elem=13,next_=None
q.next = head.next
head = q
一般情況的元素插入
- 創建一個新節點q并存入數據
- 把之前的節點pre的next存入新節點q的next
- 修改pre的next,使之指向新節點q
#時間復雜度O(n)
q = LNode(13)
q.next = pre.next
pre.next = q
刪除元素
刪除表首元素
丟棄不用的節點將被Pyhton解釋器自動回收
#O時間復雜度(1)
head = head.next
一般情況的元素刪除
#時間復雜度O(n)
pre.next = pre.next.next
掃描定位和遍歷
按下標定位掃描
Pyhton慣例,鏈表首節點的元素應該看作下標為0。確定第i個元素所在的節點:
#如果一個表頭指針的值為None說明它所引用的鏈表已經結束了
#輔助變量p為掃描指針
#每一個掃描循環必須用一個掃描指針作為控制變量
#每步迭代前都要檢查其值是否為None
#在Python中‘p is not None’可以簡寫成‘p’
p = head
while p is not None and i > 0:
i -= 1
p = p.next
按元素定位掃描
假設需要在鏈表里找到滿足謂詞pred的元素:
p = head
while p is not None and not pred(p.elem):
p = p.next
遍歷
完整的掃描稱作遍歷。
Example1 建立一個鏈表
#節點元素取整數1到10的值
llist = LNode(1)
p = llist
for i in range(2,11):
p.next = LNode(i)
p = p.next
Example2 依次輸出鏈表中各元素:
p = head
while p is not None:
print(p.elem)
p = p.next
Example3 求鏈表長度:
#時間復雜度O(n)
def get_length(head):
p, n = head, 0
while p is not None:
n += 1
p = p.next
return n
單鏈表類定義、初始化函數與常用操作
#定義節點類
class LNode:
def __init__(self, elem, next_= None):
self.elem = elem
self.next_ = next_
#定義鏈表類
class LinkedList:
#初始化函數,定義一個空鏈表
def __init__(self):
self._head = None
#prepend在頭鏈表加入新節點
def prepend(self, elem):
self._head = LNode(elem, self._head)
def append(self, elem):
p = self._head
if p is None:
p = LNode(elem)
return
while p.next is not None:
p = p.next
p.next = LNode(elem)
def printall(self):
p = self._head
while p is not None:
print p.elem, " "
p = p.next
print " "