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

数据结构与算法(python)_05_栈队列排序

2020-07-12 17:39 87 查看

文章目录

  • 队列 First In First Out
  • 排序
  • 选择排序
  • 方法二
  • 插入排序
  • 栈 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)
    稳定性:稳定

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: