一、循环队列的实现
代码解释
1、完成初始化
2、定义方法
3、测试实例
4、完整代码
javascript
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、代码
javascript
#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)完整代码
javascript
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、完整代码:
javascript
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))
三、综合
当要求排序的数和字符串量很大并存储在文件中时,实现代码如下
javascript
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