1.數據結構:線性表和鏈表、堆棧和隊列、樹和二叉樹、圖、字典和集合、B樹、哈希表
鏈表
1)含義:鏈表(Linked list)是一種常見的基礎數據結構,是一種線性表,但是並不會按線性的順序存儲數據,而是在每一個節點裏存到下一個節點的指針(Pointer)。由於不必須按順序存儲,鏈表在插入的時候可以達到O(1)的複雜度,比另一種線性表順序錶快得多,但是查找一個節點或者訪問特定編號的節點則需要O(n)的時間,而順序表相應的時間複雜度分別是O(logn)和O(1)
2)特點:使用鏈表結構可以克服數組鏈表需要預先知道數據大小的缺點,鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理。但是鏈表失去了數組隨機讀取的優點,同時鏈表由於增加了結點的指針域,空間開銷比較大
3)操作:
- is_empty() 鏈表是否爲空
- length() 鏈表長度
- travel() 遍歷鏈表
- add(item) 鏈表頭部添加
- append(item) 鏈表尾部添加
- insert(pos, item) 指定位置添加
- remove(item) 刪除節點
- search(item) 查找節點是否存在
# -*- coding: utf-8 -*-
class Node(object):
"""雙向鏈表節點"""
def __init__(self, item):
self.item = item
self.next = None
self.prev = None
class DLinkList(object):
"""雙向鏈表"""
def __init__(self):
self._head = None
def is_empty(self):
"""判斷鏈表是否爲空"""
return self._head == None
def length(self):
"""返回鏈表的長度"""
cur = self._head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
"""遍歷鏈表"""
cur = self._head
while cur != None:
print cur.item
cur = cur.next
def add(self, item):
"""頭部插入元素"""
node = Node(item)
if self.is_empty():
# 如果是空鏈表,將_head指向node
self._head = node
else:
# 將node的next指向_head的頭節點
node.next = self._head
# 將_head的頭節點的prev指向node
self._head.prev = node
# 將_head 指向node
self._head = node
def append(self, item):
"""尾部插入元素"""
node = Node(item)
if self.is_empty():
# 如果是空鏈表,將_head指向node
self._head = node
else:
# 移動到鏈表尾部
cur = self._head
while cur.next != None:
cur = cur.next
# 將尾節點cur的next指向node
cur.next = node
# 將node的prev指向cur
node.prev = cur
def search(self, item):
"""查找元素是否存在"""
cur = self._head
while cur != None:
if cur.item == item:
return True
cur = cur.next
return False
def insert(self, pos, item):
"""在指定位置添加節點"""
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
node = Node(item)
cur = self._head
count = 0
# 移動到指定位置的前一個位置
while count < (pos-1):
count += 1
cur = cur.next
# 將node的prev指向cur
node.prev = cur
# 將node的next指向cur的下一個節點
node.next = cur.next
# 將cur的下一個節點的prev指向node
cur.next.prev = node
# 將cur的next指向node
cur.next = node
def remove(self, item):
"""刪除元素"""
if self.is_empty():
return
else:
cur = self._head
if cur.item == item:
# 如果首節點的元素即是要刪除的元素
if cur.next == None:
# 如果鏈表只有這一個節點
self._head = None
else:
# 將第二個節點的prev設置爲None
cur.next.prev = None
# 將_head指向第二個節點
self._head = cur.next
return
while cur != None:
if cur.item == item:
# 將cur的前一個節點的next指向cur的後一個節點
cur.prev.next = cur.next
# 將cur的後一個節點的prev指向cur的前一個節點
cur.next.prev = cur.prev
break
cur = cur.next
ll = DLinkList()
ll.add(1)
ll.add(2)
ll.append(3)
ll.insert(2, 4)
ll.insert(4, 5)
ll.insert(0, 6)
print '----------------1-----------------'
print "length:",ll.length()
print '----------------2-----------------'
ll.travel()
print '----------------3-----------------'
print ll.search(3)
print ll.search(4)
print '----------------4-----------------'
ll.remove(1)
print "length:",ll.length()
print '----------------5-----------------'
ll.travel()
4)輸出:
堆棧
1.含義:堆棧(英語:stack),也可直接稱棧,在計算機科學中,是一種特殊的串列形式的數據結構,它的特殊之處在於只能允許在鏈接串列或陣列的一端(稱爲堆疊頂端指標,英語:top)進行加入資料(英語:push)和輸出資料(英語:pop)的運算。另外堆疊也可以用一維陣列或連結串列的形式來完成。堆疊的另外一個相對的操作方式稱爲佇列;由於堆疊數據結構只允許在一端進行操作,因而按照後進先出(LIFO, Last In First Out)的原理運作
2.特點:先入後出,後入先出;除頭尾節點之外,每個元素有一個前驅,一個後繼
3.操作:
- is_empty:判斷棧是否爲空
- peek:返回棧頂元素
- size:返回棧的大小
- push:把新的元素堆進棧裏面
- pop:把棧頂元素丟出去
# -*- coding: utf-8 -*-
class Stack(object):
__slots__ = ('__items') #限定Stack類的成員只有__items(類成員)
# 初始化棧爲空列表
def __init__(self):
self.__items = []
# 判斷棧是否爲空,返回布爾值
def is_empty(self):
return self.__items == []
# 返回棧頂元素
def peek(self):
return self.__items[len(self.__items) - 1]
# 返回棧的大小
def size(self):
return len(self.__items)
# 把新的元素堆進棧裏面(程序員喜歡把這個過程叫做壓棧,入棧,進棧……)
def push(self, item):
self.__items.append(item)
# 把棧頂元素丟出去(程序員喜歡把這個過程叫做出棧……)
def pop(self):
return self.__items.pop()
# 初始化一個棧對象
my_stack = Stack()
# 把'h'丟進棧裏
my_stack.push('h')
# 把'a'丟進棧裏
my_stack.push('a')
# 看一下棧的大小(有幾個元素)
print my_stack.size()
# 打印棧頂元素
print my_stack.peek()
# 把棧頂元素丟出去,並打印出來
print my_stack.pop()
# 再看一下棧頂元素是誰
print my_stack.peek()
# 這個時候棧的大小是多少?
print my_stack.size()
# 再丟一個棧頂元素
print my_stack.pop()
# 看一下棧的大小
print my_stack.size
# 棧是不是空了?
print my_stack.is_empty()
4)輸出:
隊列
1)含義:和堆棧類似,唯一的區別是隊列只能在隊頭進行出隊操作,所以隊列是是先進先出(FIFO, First-In-First-Out)的線性表
2)特點:先入先出,後入後出;除尾節點外,每個節點有一個後繼;(可選)除頭節點外,每個節點有一個前驅
3)操作:
- inqueue():一次入隊一個
- many_in_queue():一次入隊多個
- outqueue():出隊
- show():顯示隊列
- head():隊列的頭部
- tail():隊列的尾部
- isempty():判斷隊列是否爲空
- length():隊列長度
# -*- coding: utf-8 -*-
class queue(object):
def __init__(self):
self.queue = []
# 一次入隊一個
def inqueue(self,item):
self.queue.append(item)
# 一次入隊多個
def many_in_queue(self,*args):
self.queue.extend(args)
# 出隊
def outqueue(self):
if not self.queue == []:
self.queue.pop(0)
else:
return None
# 顯示隊列
def show(self):
for i in self.queue:
print i
# 隊列的頭部
def head(self):
if not self.queue == [] :
print self.queue[0]
else :
return None
# 隊列的尾部
def tail(self):
if not self.queue == []:
print self.queue[-1]
else :
return None
# 是否爲空
def isempty(self):
return self.queue == []
# 長度
def length(self):
print len(self.queue)
q1 = queue()
q1.inqueue(1)
q1.show()
print '----------1-----------'
q1.many_in_queue(3,4,5)
q1.show()
print '----------1-----------'
q1.outqueue()
q1.show()
print '----------1-----------'
q1.head()
print '----------1-----------'
q1.tail()
print '----------1-----------'
q1.length()
q1.isempty()
4)輸出:
二叉樹
1)定義:二叉樹是每個結點最多有兩個子樹的樹結構。它有五種基本形態:二叉樹可以是空集;根可以有空的左子樹或右子樹;或者左、右子樹皆爲空
2)特點:性質1:二叉樹第i層上的結點數目最多爲2i-1(i>=1);性質2:深度爲k的二叉樹至多有2k-1個結點(k>=1);性質3:包含n個結點的二叉樹的高度至少爲(log2n)+1;性質4:在任意一棵二叉樹中,若終端結點的個數爲n0,度爲2的結點數爲n2,則n0=n2+1
3)操作
# -*- coding: utf-8 -*-
class Node(object):
def __init__(self,item):
self.item = item
self.child1 = None
self.child2 = None
class Tree(object):
def __init__(self):
self.root = None
def add(self, item):
node = Node(item)
if self.root is None:
self.root = node
else:
q = [self.root]
while True:
pop_node = q.pop(0)
if pop_node.child1 is None:
pop_node.child1 = node
return
elif pop_node.child2 is None:
pop_node.child2 = node
return
else:
q.append(pop_node.child1)
q.append(pop_node.child2)
def traverse(self): # 層次遍歷
if self.root is None:
return None
q = [self.root]
res = [self.root.item]
while q != []:
pop_node = q.pop(0)
if pop_node.child1 is not None:
q.append(pop_node.child1)
res.append(pop_node.child1.item)
if pop_node.child2 is not None:
q.append(pop_node.child2)
res.append(pop_node.child2.item)
return res
def preorder(self,root): # 先序遍歷
if root is None:
return []
result = [root.item]
left_item = self.preorder(root.child1)
right_item = self.preorder(root.child2)
return result + left_item + right_item
def inorder(self,root): # 中序序遍歷
if root is None:
return []
result = [root.item]
left_item = self.inorder(root.child1)
right_item = self.inorder(root.child2)
return left_item + result + right_item
def postorder(self,root): # 後序遍歷
if root is None:
return []
result = [root.item]
left_item = self.postorder(root.child1)
right_item = self.postorder(root.child2)
return left_item + right_item + result
t = Tree()
for i in range(10):
t.add(i)
print u'層序遍歷:',t.traverse()
print u'先序遍歷:',t.preorder(t.root)
print u'中序遍歷:',t.inorder(t.root)
print u'後序遍歷:',t.postorder(t.root)
4)輸出: