三向字符串快速排序——python实现

为啥写这个

  因为yh老师布置了这个高算作业,可怜我的国庆假期就这么没了,不过能有所得总是好的,所以记录一下

三向字符串快速排序是什么

首先快速排序是什么?
  快速排序是这么做的:
  1、用一个字符作为基准值(一般默认第一个为基准值),比它大的移到它的右边,比它小的移到它左边。
  2.这样就分成了三块,大于小于和等于三组
  3.然后每一块再次重复步骤一,又分成小组,直到不能再分

那么三向字符串快速排序又是什么?
  和快排一样,只是他需要先从首字母比较单词大小,如果遇到同字母,还要再次比较下一个字母,如图所示(图是用别人的哈)
在这里插入图片描述
  所以你会发现:三向字符串快速排序==快排+从左向右依次比较单词字母大小排序

我做了什么

  刚开始,我真的按照思路去走了,我这么走的:
  从首字母开始不断快排,每次快排都会分出三个组,left,mid和right,那么mid那一组一定是首字母相同的呀,那就mid那一组下一个字母再次快排呀,这样不就行了

def quick_sort(list,start,end,num):#num表示第几个字母
	value=list[start]
	right=[]
	left=[]
	mid=[]
	result=[]
	for i in range(end):
		if list[i]>value:
			right.append(list[i])
		elif list[i]<value:
			left.append(list[i])
		else:
			mid.append(list[i])
			if len(mid)>1:
				quick_sort(mid,0,len(mid)-1,1)
				
	result=left+mid+right
	if len(left)>1:
		quick_sort(left,0,len(left)-1,0)
	if len(right)>1:
		quick_sort(right,0,len(right)-1,0)

  可是!!我这样写了之后,他给我报错了?!!当然我的代码坑定是有问题的,因为我没有交换啥的,一定还有解决办法

RecursionError: maximum recursion depth exceeded in comparison

  然后我调试的时候,发现,机器自己就可以从左到右顺序比较字母排序呀!!那我还乱啥呀?直接快派它不香吗?

开玩笑,作业要认真做,原理也是要搞懂的
  问了下同组计算机出身的sc大佬,明白了:计算机不明白除了数字外的东西怎么比较大小,那怎么办呢,那就字符串对应数字呗,这样比较字符串的时候就是在比较它们对应的数字,很多语言里面都是早就写有这种默认规则的,要么可以直接用,要么用个函数啥的。
  顺带一提,python的列表中有个sort函数,直接用就可以排好顺序,但是他的排序原理是timsort。

list.sort(cmp=None, key=None, reverse=False)
'''
cmp -- 可选参数, 如果指定了该参数会使用该参数的方法进行排序。
python3.x中取消了cmp参数,也不支持直接往sort()里面传函数,但可以构造排序函数传递给key来实现。
key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。比如第几个字母等等
reverse -- 排序规则,reverse = True 降序, reverse = False 升序(默认)'''

  所以,接下来的事情的思路就清晰了,在快排的基础上,揪出中间的部分,在中间的部分用下一个字母再次快排

Python的实现

  先附上快速排序的代码:

def quick_sort(alist, start, end):
    """快速排序"""
    if start >= end:  # 递归的退出条件
        return
    mid = alist[start]  # 默认第一个为基准值
    low = start  # low在最左边的开始位置,是个由左向右移动的游标
    high = end  # low在最右边的末尾位置,是个由右向左移动的游标
    while low < high:
        # 如果low与high未重合,high此时对应的值大于等于基准值,则high左移
        while low < high and alist[high] >= mid:
            high -= 1
        alist[low] = alist[high]
        # 如果low与high未重合,low指向的元素比基准元素小,则low向右移动
        while low < high and alist[low] < mid:
            low += 1
        alist[high] = alist[low]
        #low和high遇到为一次,一次有一个基准值,high和low互换就会有空位出现,方便移动元素

    # 退出循环后,low与high重合,此时所指位置为基准元素的正确位置,左边的元素都比基准元素小,右边的元素都比基准元素大
    alist[low] = mid  # 将基准元素放到该位置,
    # 对基准元素左边的子序列进行快速排序

    quick_sort(alist, start, low - 1)  # start :0  low -1 原基准元素靠左边一位
    # 对基准元素右边的子序列进行快速排序
    quick_sort(alist, low + 1, end)  # low+1 : 原基准元素靠右一位  end: 最后

'''读取输入数据'''
input = []

with open("用的是txt文件里的三字母单词做数据,这里写的是txt地址", "r") as f:
    linedata = f.readlines()  # 读全部
    for line in linedata:
        words = line.split()  # 空格消除
        for i in words:
            input.append(i)#变成单个单词
# print(input[5][0])
f.close


if __name__ == '__main__':
    quick_sort(input, 0, len(input) - 1)
    print(input)

  然后是三向字符串快速排序的代码:当然这个就没办法去给数字排序了,因为写了限定字母的部分

#用来确定列表里面第几个单词的第几个字母在比较
def CharAt(str,num):
    if num<len(str):
        return str[num]

def Quick3String(alist,start,end,num):
    #括号里的内容分别是输入的单词列表,开始单词的序号,结尾单词的序号,在比较的第几个字母
    if end<=start:#边界条件
        return
    low=start#左边游标
    high=end#右边游标
    base = CharAt(alist[low], num)#默认第一个单词为基准值
    i = low + 1    # 从基准之后一个开始比较
    while i<=high:#不重叠的情况下
        current = CharAt(alist[i], num)#一定要在循环里面,每次会变的
        if current<base:#小了就换,排成从小到大的顺序
            alist[low],alist[i]=alist[i],alist[low]
            low = low + 1
            i = i + 1
        elif current>base:
            alist[high],alist[i]=alist[i],alist[high]
            high=high-1
        else:#相等的只移动游标
            i=i+1

    Quick3String(alist, start, low-1, num)

    if len(base)>0:
        Quick3String(alist, low, high, num+1)

    Quick3String(alist, high+1, end, num)

  这是结果(部分)在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值