数据结构与算法(python)_05_栈队列排序
文章目录
栈 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)
稳定性:稳定
- 如何根据字典值的大小,对字典中的项排序---Python数据结构与算法相关问题与解决技巧...
- 数据结构与算法(八):归并排序的python实现
- python数据结构与算法 31 选择排序
- 数据结构与算法(Python)——常见数据结构Part3(队列和循环队列)
- 用Python实现的数据结构与算法-队列
- Python_Day_05 计数器(counter),有序字典(OrderDict),默认字典(defaultdict),可命名元祖(namedtuple),双向队列(deque),单项队列(deuqe.Queue)
- python数据结构与算法----插入排序
- 数据结构与算法(五):插入排序的python实现
- python 栈和队列 排序 初级数据结构
- python 在列表中完成队列的删除和排序
- 基于Python的数据结构与算法-队列
- 算法基础:排序(四)——二叉堆、优先队列、堆排序——Python实现
- 算法基础:排序(四)——二叉堆、优先队列、堆排序——Python实现
- python数据结构与算法----选择排序
- 用Python 学习数据结构与算法 三、选择排序
- 数据结构与算法(四):选择排序的python实现
- 用Python实现的数据结构与算法:双端队列
- python数据结构与算法 14 队列的python实现
- python数据结构与算法 15 队列应用之烫手的山芋
- Python实现数据结构与算法——队列的最大值