您的位置:首页 > 理论基础 > 数据结构算法

1、Python 基本数据结构

2017-07-25 17:12 225 查看

一、线性数据结构

1. 线性数据结构的特点

数据项之间只存在先后的次序关系,新的数据项加入到数据集中时,只会加入到原有某个数据项之前或之后

线性结构总有两端:左右端、前后端、顶端底端等,但两端的称呼并不是关键,不同线性结构的关键区别在于数据项增减的方式

有的结构只允许数据项从一端添加,而有的结构则允许数据项从两端移除

2. 线性数据结构分类

栈(stack)

队列(queue)

双端队列(deque)

链表(LinkedList)

二、栈(stack)

1. 栈的特点

栈是一种
有次序
的数据项集合,在栈中,数据项的
加入和移除
都仅发

生在
栈顶


后进先出:
Last in First out(LIFO),eg: word 中的 undo


反转次序

2. 使用列表来模拟栈

假设栈要实现如下功能:



代码实践

# 选用 List 的尾端(index=-1)作为栈顶,此时push/pop的复杂度为O(1)
# 若选用 List 的首端(index=0)作为栈顶,其push/pop的复杂度为O(n),因为要用pop(0),insert(0,item)等来模拟出栈和入栈

class Stack:
"""使用 list 来模拟栈"""
def __init__(self):
self.items = []

def isEmpty(self):
return self.items == []

def push(self, item):
self.items.append(item)

def pop(self):
if not self.isEmpty():
return self.items.pop()

def peek(self):
if not self.isEmpty():
return self.items[len(self.items)-1]

def size(self):
return len(self.items)

s = Stack()
s.isEmpty() = True
s.push(4)
s.push('dog')
s.peek() = 'dog'
s.size() = 2
s.pop() = 'dog'
s.pop() = 4


三、队列(queue)

1. 队列的特点

队列是一种
有次序
的数据集合,新数据项的
添加
总发生在尾端(
rear
),而现存数据项的移除总发生在首端(
front
)

先进先出:
First in First out(FIFO),eg: 打印队列


队列仅有一个入口和一个出口,不允许数据项直接插入队中,也不允许从中

间移除数据项



2. 使用列表来模拟队列

假设队列要实现如下功能:



代码实践

# 将 list 的首端作为队列的尾端,list 的末端作为队列的首端
class Queue:
"""使用 list 来模拟队列"""
def __init__(self):
self.items = []

def isEmpty(self):
return self.items == []

def enqueue(self, item):
self.items.insert(0, item)

def dequeue(self):
if not self.isEmpty():
return self.items.pop()

def size(self):
return len(self.items)

q=Queue()
q.enqueue(4) = [4]
q.enqueue('dog') = ['dog', 4]
q.size() = 2
q.isEmpty() = False
q.dequeue() # 4 出队,list 中还剩['dog']


四、双端队列(deque)

1. 双端队列的特点

双端队列是一种
有次序
的数据集,其
首端和尾端
都可以加入数据和移除数据

某种意义上说,双端队列集成了栈和队列的能力,但双端队列并不具有内在的
LIFO
或者
FIFO
特性,如果用双端队列来模拟栈或队列,需要由使用者
自行维护操作的一致性




2. 使用列表来模拟双端队列

假设栈要实现如下功能:



# 将 list 的首端作为双端队列的尾端,list 的末端作为双端队列的首端
class Deque:
"""使用 list 来模拟双端队列"""
def __init__(self):
self.items = []

def isEmpty(self):
return self.items == []

def addFront(self, item):
self.items.append(item)

def addRear(self, item):
self.items.insert(0,item)

def removeFront(self):
if not self.isEmpty():
return self.items.pop()

def removeRear(self):
if not self.isEmpty():
return self.items.pop(0)

def size(self):
return len(self.items)

d=Deque()
d.addRear(4) = [4]
d.addRear('dog') = ['dog', 4]
d.addFront('cat') = ['dog', 4, 'cat']
d.size() = 3
d.removeRear() # 移除'dog', 还剩[4, 'cat']
d.removeFront() # 移除'cat', 还剩[4]


五、链表(LinkedList)

1. 链表简介

链表是实现了数据之间保持逻辑顺序(通过引用实现),但存储空间不必按顺序的方法

链表中的基本要素:

节点:每一个节点有两个域,左边部份叫值域,用于存放用户数据;右边叫指针域,一般是存储着到下一个元素的指针(python 中使用引用来实现)

head 节点:没有值域,只有指针域且永远指向第一个节点

tail 节点:有值域,有指针域但永远指向 None

使用链表的好处

插入删除速度很快,不用对整个链表进行调整

能够动态的进行存储分配

移除链表中某元素示例



2. 使用类来模拟链表(待扩展…)

假设链表要实现如下功能:



代码实践

# 节点类
class Node:
def __init__(self, init_data):
self.data = init_data
self.next = None

def get_data(self):
return self.data

def get_next(self):
return self.next

def set_data(self, new_data):
self.data = new_data

def set_next(self, new_next):
self.next = new_next

# 链表类
class LinkedList:
def __init__(self):
self.head = None

def is_empty(self):
return self.head == None

# 从链表头插入对象
def add(self,item):
temp = Node(item)
temp.set_next(self.head)  # 将链表头指向的下一个对象的地址赋给待插入对象
self.head = temp          # 将待插入对象的地址赋给链表头

# 遍历链表,取得其长度
def size(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.get_next()
return count

# 判断某元素是否在链表中
def search(self,item):
current = self.head
found = False
while current != None and not found:
if current.get_data() == item:
found = True
else:
current = current.get_next()
return found

# 移除链表中的某个元素
def remove(self,item):
current = self.head
previous = None
found = False
while not found:
if current.get_data() == item:
found = True
else:
previous = current
current = current.get_next()
if previous == None:
self.head = current.get_next()
else:
previous.set_next(current.get_next())


六、参考资料

1、北大数据结构与算法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: