数据结构与算法(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)
稳定性:稳定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值