文章目录
栈 LIFO, Last In First Out
栈(stack),有些地方称为堆栈,是一种容器,可存入数据元素、访问元素、删除元素,它的特点在于只能允许在容器的一端(称为栈顶端指标,英语:top)进行加入数据(英语:push)和输出数据(英语:pop)的运算。没有了位置概念,保证任何时候可以访问、删除的元素都是此前最后存入的那个元素,确定了一种默认的访问顺序。
栈描述的是操作,顺序表链表描述的是数据的存放。
由于栈的特点,我们可以用栈来解析算数表达式求值:python解析算数表达式求值
栈的实现
栈的操作
Stack() 创建一个新的空栈
push(item) 添加一个新的元素item到栈顶
pop() 弹出栈顶元素
peek() 返回栈顶元素
is_empty() 判断栈是否为空
size() 返回栈的元素个数
可以用顺序表,也可以用链表,这里用顺序表list实现
class Stack(object):
def __init__(self):
self.__list = []
def push(self,item):
#对于顺序表在头部操作时间复杂度为O(n),所以这里选择在尾部操作O(1)
#如果是链表,则选择在头部操作O(1),尾部操作时间复杂度为O(n)
#self.__list.insert(0,item)
self.__list.append(item)
def pop(self):
#不在头部操作#self.__list.pop(0)
return self.__list.pop()
def peek(self):
if self.__list:
return self.__list[-1]
else:
return None
def is_empty(self):
return self.__list == []
#return not self.__list #这里空列表为False,加not,显示is_empty为真
def size(self):
return len(self.__list)
队列 First In First Out
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列的实现
同栈一样,队列也可以用顺序表或者链表实现。
操作
Queue() 创建一个空的队列
enqueue(item) 往队列中添加一个item元素
dequeue() 从队列头部删除一个元素
is_empty() 判断一个队列是否为空
size() 返回队列的大小
class Queue(object):
def __init__(self):
self.__list = []
#如果队列插入数据更频繁,就减少插入数据的时间复杂度,选择append到list的尾部,那么弹出数据就要设置从头部弹,反之。
def enqueue(self, item):
self.__list.append(item)
# self.__list.insert(0,item)
def dequeue(self):
return self.__list.pop(0)
# return self.__list.pop()
def is_empty(self):
return self.__list == []
#return not self.__list #这里空列表为False,加not,显示is_empty为真
def size(self):
return len(self.__list)
双端队列的实现
双端队列(deque,全名double-ended queue),是一种具有队列和栈的性质的数据结构。
双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。双端队列可以在队列任意一端入队和出队。
操作
Deque() 创建一个空的双端队列
add_front(item) 从队头加入一个item元素
add_rear(item) 从队尾加入一个item元素
remove_front() 从队头删除一个item元素
remove_rear() 从队尾删除一个item元素
is_empty() 判断双端队列是否为空
size() 返回队列的大小
class Dqueue(object):
def __init__(self):
self.__list = []
def add_front(self, item):
self.__list.insert(0,item)
def add_rear(self, item):
self.__list.append(item)
def pop_front(self):
return self.__list.pop(0)
def pop_rear(self):
return self_list.pop()
def is_empty(self):
return self.__list == []
#return not self.__list #这里空列表为False,加not,显示is_empty为真
def size(self):
return len(self.__list)
排序
排序算法(英语:Sorting algorithm)是一种能将一串数据依照特定顺序进行排列的一种算法。
排序算法的稳定性
稳定性:稳定排序算法会让原本有相等键值的纪录维持相对次序。
排序前:(4, 1) (3, 1) (3, 7)(5, 6)
排序后:
情况一:(3, 1) (3, 7) (4, 1) (5, 6) (维持次序)
情况二:(3, 7) (3, 1) (4, 1) (5, 6) (次序被改变)
上述情况一就是稳定的排序算法的输出结果。
冒泡排序
冒泡排序(英语:Bubble Sort)
- 比较相邻的元素。大的放后面,第一轮能让最大的放在最后面
- 需要进行n-1轮排序,第二轮得到第二大的元素放在倒数第二个依次类推
- 直到没有任何一对数字需要比较。
时间复杂度
最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
最坏时间复杂度:O(n^2)
稳定性:稳定
写法一
def bubble_sort(alist):
for j in range(len(alist)-1):
count = 0
# 这里不操作元素,而是选择操作元素下标,后面交换元素位置也会更方面
# 因为i从0开始与后一个比较,到倒数第二个刚好跟最后一个比较,倒数第二个元素下标为n-2
# for i in range(0,len(alist)-1): #因为i指的是下标,第n-1个元素下标为n-2
for i in range(0,len(alist)-1-j): #每经过一轮少排一个
if alist[i] > alist[i+1]:
alist[i],alist[i+1] = alist[i+1],alist[i]
count += 1
if count == 0: #如果一轮循环没有一个需要改变,那么直接输出
return
写法二
range(len(alist)-1,0,-1):表示从len(alist)-1开始,到0为止,取其中所有整数
def bubble_sort2(alist):
for j in range(len(alist)-1,0,-1):
# j表示每次遍历需要比较的次数,是逐渐减小的
for i in range(j):
if alist[i] > alist[i+1]:
alist[i],alist[i+1] = alist[i+1],alist[i]
选择排序
选择排序(Selection sort)
每次把列表分为两部分,每一轮从乱序部分选出最小加入有序部分。
- 每次选择未排序部分的最小值,放到与未排序的第一位进行交换
- 然后继续在未排序的部分继续选择再排序,直到第n-1位排好
方法一
def select_sort(alist):
for j in range(len(alist)-1):
min_index = 0
for i in range(j+1,len(alist)):
if alist[min_index] > alist[i]:
min_index = i
alist[j],alist[min_index] = alist[min_index],alist[j]
时间复杂度
最优时间复杂度:O(n2)
最坏时间复杂度:O(n2)
稳定性:不稳定(考虑升序每次选择最大的情况)
方法二
比较pythonic的写法
# 选择排序一般时间复杂度为O(n^2); python可以在列表中通过min(iList[i:])得到最小数,所以时间复杂度为 O(n)
def selectionSort(iList):
if len(iList) <= 1:
return iList
for i in range(0, len(iList)-1):
if iList[i] != min(iList[i:]):
minIndex = iList.index(min(iList[i:]))
iList[i], iList[minIndex] = iList[minIndex], iList[i]
print("第 %d 轮排序结果:" %i, end="")
print(iList)
return iList
时间复杂度
选择排序一般时间复杂度为O(n^2); python可以在列表中通过**min(iList[i:])**得到最小数,所以时间复杂度为 O(n)
插入排序
选择排序是选出每轮最小的放进去;插入排序是每轮拿下一个比大小后插入。
插入排序(英语:Insertion Sort)
- 将列表分为两部分
- 从乱序中直接拿出下一个
- 在有序部分进行排序。
def insert_selection(alist):
for i in range(1,len(alist)): #从第二个数开始
while i > 0:
if alist[i] < alist[i-1]: #如果比前一个小,就往前挪
alist[i],alist[i-1] = alist[i-1],alist[i]
i -= 1
else:
break
def insert_selection2(alist):
for i in range(1,len(alist)):
for j in range(i,0,-1):
if alist[j] < alist[j-1]:
alist[j],alist[j-1] = alist[j-1],alist[j]
时间复杂度
最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
最坏时间复杂度:O(n2)
稳定性:稳定