循环队列的实现及应用——桶排序bucket_sort、基数排序radix_sort

一、循环队列的实现

代码解释

1、完成初始化

在这里插入图片描述

2、定义方法

在这里插入图片描述

3、测试实例

在这里插入图片描述

4、完整代码

class AQueue:
    def __init__(self, size=10):
        self.__mSize = size
        self.__front=0
        self.__rear = 0
        self.__listArray = [None] * size

    #清空元素
    def clear(self):
        self.__front = 0
        self.__rear = 0
        for i in range(self.__mSize):
            self.__listArray[i]=None
    # 入队操作
    def enqueue(self, item):
        if not self.is_full():
            self.__rear=(self.__rear+1)%self.__mSize
            self.__listArray[self.__rear]=item
        elif self.is_full():
            raise ValueError("Queue is Full.")
    # 出队操作
    def dequeue(self):
        if not self.is_empty():
            self.__front=(self.__front+1)%self.__mSize
            self.item=self.__listArray[self.__front]
            self.__listArray[self.__front]=None
            return self.item
        elif self.is_empty():
            raise ValueError("Queue is empty.")
    # 判空,检查队列是否为空
    def is_empty(self):
        return self.__front==self.__rear
    # 判满,注意并不是所有的位置都有元素才是满,当只有一个是None时就满了,有点像链表的哑结点
    def is_full(self):
        return ((self.__rear+1)%self.__mSize==self.__front)

    def __repr__(self):  # 显示队列中所有元素,数组切片左闭右开
        return str(self.__listArray[:self.__mSize])

if __name__=='__main__':
    queue=AQueue(5)
    queue.enqueue(1)
    print(queue)
    print(queue.dequeue())
    queue.enqueue(2)
    queue.enqueue(3)
    queue.enqueue(4)
    print(queue)
    print(queue.dequeue())
    queue.enqueue(5)
    print(queue)
    queue.enqueue(6)
    print(queue.is_full())
    print(queue)
    queue.dequeue()
    print(queue)

二、队列的应用——桶排序bucket_sort

对于排序法,我们已经学了三种简单排序:直接插入排序、冒泡排序、选择排序,快速排序、归并排序。那为什么还要学习桶排序呢?
因为前面提到的几种排序方法全是基于比较的排序,时间复杂度在最好的情况下才是O(nlogn)
而桶排序没有用比较就将数字排好序了,虽然以消耗空间为代价,但是时间复杂度得到了很大的提升

1、图示

在这里插入图片描述

2、代码

在这里插入图片描述

#s代表待排序数组,m代表最大元素值,n代表元素个数
from AQueue import *
def bucket_sort(s,m,n):
    #创建m+1个桶
    b = [AQueue() for _ in range(0, m + 1)]
    #把对应的数字放进去
    for i in range(0,n):
        b[s[i]].enqueue(s[i])
    for j in range(0, m + 1):#检查桶
        print(b[j])
    i=0
    for j in range(0,m+1):#依次遍历桶并出队到s中
        while b[j].is_empty()==False:
            s[i]=b[j].dequeue()
            i+=1
    print(s)

s=[3,1,2,5,1,2,3]
bucket_sort(s,5,7)

3、时间复杂度分析

在这里插入图片描述
当m<n时,桶排序的时间复杂度会降到O(n)
但是当待排序数是[2,3,4,6666]
那么m=6666,要创建6667个队列显然造成了空间的极度浪费
并且O(m)也不一定会比O(nlogn)好到哪里去
因此接下来我们引入桶排序的升级版——基数排序

二、桶排序升级版——基数排序radix_sort

(一)对数字进行排序

1、图示

在这里插入图片描述
假设还用桶排序,上面这个例子要创建673个桶
而基数排序分别把位数看作一趟分配回收
最多有几位就进行几趟分配回收

2、代码

注意代码中print()的地方,将有助理解代码运行效果,输出样例已给出

(1)代码总览

在这里插入图片描述

(2)测试样例

在这里插入图片描述

(3)完整代码
from AQueue import *
def radix_sort_nums(s):
    # 计算扫描趟数:最长字符串长度
    circulation=len(str(max(s)))
    # 开始扫描,从个位开始 i=0是个位
    for i in range(circulation):
        # 计算桶的边界
        unit_ten_hundred_values = []#存放个位十位等的值
        count = [0] * 10
        for j in s:
            unit_ten_hundred_value = (j // (10 ** i)) % 10  # 个位数:j//0
            count[unit_ten_hundred_value] += 1#个位数是几,对应的下标的桶里就应该多一个位置
            unit_ten_hundred_values.append(unit_ten_hundred_value)#把这个数的个位数放进去
        print(unit_ten_hundred_values)
        print(count)
        # 创建10个桶,每个桶有边界(由于有一个位置是相当于哑结点的作用,所以要加一)
        b = []
        for k in count:
            b.append(AQueue(k + 1))
        print(b)
        # 把对应的数字放进去
        for i in range(len(s)):#个位数值放到对应的桶中,但是入队的是s里的值,而非个位数值
            b[unit_ten_hundred_values[i]].enqueue(s[i])
        for j in range(10):  # 检查桶
            print(b[j])
        i = 0
        for j in range(10):  # 依次遍历桶并出队到s中
            while b[j].is_empty() == False:
                s[i] = b[j].dequeue()
                i += 1
        print(s)
    print(s)

s=[200,321,453,673,72,63]
radix_sort_nums(s)

(二)对字符串进行排序

和对数组的排序一样,对字母的排序实质上是对其ASCII码的排序

1、代码总览

在这里插入图片描述

2、完整代码:

from AQueue import *
# 针对字符串的基数排序
def radix_sort_str(arr):
    # 计算最长字符串的长度
    max_len = max(len(s) for s in arr)

    # 进行max_len次排序,每次按一个字符排序
    for i in range(max_len - 1, -1, -1):  # 从最高位到最低位排序
        # 创建58个桶(ASCII字符集大小)大写A65~小写z122
        buckets = [AQueue(1000) for _ in range(58)]
        # 将字符串分配到对应的桶中
        for s in arr:
            # 分配桶
            buckets[ord(s[i])-65].enqueue(s)
        # 回收所有桶中的字符串,并放回arr中
        i = 0
        for j in range(58):  # 依次遍历桶并出队到s中
            while buckets[j].is_empty() == False:
                arr[i] = buckets[j].dequeue()
                i += 1
    return arr

# 示例字符串数组
arr = ["ErAfCDdQ", "LVVzAQtE", "mhcyRgzp", "aOwDbbJa", "WfHWOdtb", "gOLsdkrf"]
# 对字符串数组进行基数排序
sorted_arr = radix_sort_str(arr)
# 打印排序后的结果
print(sorted_arr)
#验证
print(sorted(arr))

三、综合

当要求排序的数和字符串量很大并存储在文件中时,实现代码如下

from AQueue import *
def radix_sort_nums(s):
    #计算扫描趟数:最长数字长度
    circulation=len(str(max(s)))
    # 开始扫描,从个位开始 i=0是个位
    for i in range(circulation):
        # 计算桶的边界
        unit_ten_hundred_values=[]#存放个位十位等的值
        count = [0] * 10
        for j in s:
            unit_ten_hundred_value = (j // (10 ** i)) % 10  # 个位数:j//0
            count[unit_ten_hundred_value] += 1
            unit_ten_hundred_values.append(unit_ten_hundred_value)

        #创建10个桶,每个桶有边界
        b=[]
        for k in count:
            b.append(AQueue(k+1))
        # 把对应的数字放进去
        for i in range(len(s)):
            b[unit_ten_hundred_values[i]].enqueue(s[i])
        i = 0
        for j in range(10):  # 依次遍历桶并出队到s中
            while b[j].is_empty() == False:
                s[i] = b[j].dequeue()
                i += 1
    print(s)

def radix_sort_str(arr):
    # 计算最长字符串的长度
    max_len = max(len(s) for s in arr)

    # 进行max_len次排序,每次按一个字符排序
    for i in range(max_len - 1, -1, -1):  # 从最高位到最低位排序
        # 创建58个桶(ASCII字符集大小)大写A65~小写z122
        buckets = [AQueue(1000) for _ in range(58)]
        # 将字符串分配到对应的桶中
        for s in arr:
            # 分配桶
            buckets[ord(s[i])-65].enqueue(s)
        # 回收所有桶中的字符串,并放回arr中
        i = 0
        for j in range(58):  # 依次遍历桶并出队到s中
            while buckets[j].is_empty() == False:
                arr[i] = buckets[j].dequeue()
                i += 1
    return arr

def read_file_nums(filename):
    f=open(filename,'r')
    datas=f.read()
    f.close()
    s=datas.split()
    s=[int(item) for item in s]
    return s

def read_file_str(filename):
    f=open(filename,'r')
    datas=f.read()
    f.close()
    s=datas.split()
    return s

def main():
    # 整数类型数据排序
    s = read_file_nums('radix1.txt')
    radix_sort_nums(s)
    print("Sorted integer data:")
    print(s)

    # # 字符串类型数据排序
    str_data = read_file_str('radix2.txt')
    sorted_str_data = radix_sort_str(str_data)
    print("\nSorted string data:")
    print(sorted_str_data)

if __name__ == "__main__":
    main()

radix1.txt
在这里插入图片描述
radix2.txt
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值