查找K个最小的元素------Python版

本文档展示了多种排序算法(冒泡、堆、插入、快速、选择)在寻找随机数列表中最小k个元素的应用。通过Python实现并使用装饰器测量运行时间,对不同大小的k进行了测试。例如,查找10000个数中的1000个最小元素,堆排序最快,仅需0.04563秒。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

这里用了时间cal_time)

1.冒泡排序ubble_Sort)

2.堆排序方法(Heap_Sort)

3.插入排序方法(Insert_Sort)

4.快速排序方法(Quick_Sort)

5.选择排序方法(Select_Sort)

6.其他方法1(Other_demo1)

7.其他方法2(可能是修改的堆排序)(Other_Sort)


题目

25. 查找最小的k个元素
【问题描述】
输出一组元素中的最小的k个元素。例如数据集为:{1、8、3、6、5、4、7、2},则最小的4个数字为1,2,3和4。
【基本要求】
由随机数产生测试数据,测试数据不小于10000个,测试k的不同取值对算法的影响,如k=10、50、100、500、1000、2000等;在课程设计文档中给出测试结果的表格。
多种算法实现,如借助选择排序、堆排序、快速排序的思想等。

这里用了时间cal_time)

"""
作者:佩大奇
日期:2022/03/12/
"""
import time
from functools import wraps

def timefn(fn):
    """计算性能的修饰器"""
    @wraps(fn)
    def measure_time(*args, **kwargs):
        t1 = time.time()
        result = fn(*args, **kwargs)
        t2 = time.time()
        print("----------------------------------------------------------------")
        print("需要时间:",end=" ")
        print(f"@timefn: {fn.__name__} took {t2 - t1: .5f} s")
        print("---------------------------------------------------------------------")
        return result
    return measure_time

1.冒泡排序ubble_Sort)

"""
作者:佩大奇
日期:2022/03/05/
描述:冒泡排序:n个元素的排序需要走n-1趟循环,每一趟都能确定一个有序元素,无序元素会减少一个,直到n-1次后,n个元素去拿不变成有序的
new_knowledge:生成随机数:import random      li=[random.randint(0,1000) for i in range(1000)]
速度:10000数里查找100个需要8.7秒,,查找1000个需要时间: @timefn: bubble_ascending_order took  9.53628 s

题目:
25. 查找最小的k个元素
【问题描述】
输出一组元素中的最小的k个元素。例如数据集为:{1、8、3、6、5、4、7、2},则最小的4个数字为1,2,3和4。
【基本要求】
由随机数产生测试数据,测试数据不小于10000个,测试k的不同取值对算法的影响,如k=10、50、100、500、1000、2000等;在课程设计文档中给出测试结果的表格。
多种算法实现,如借助选择排序、堆排序、快速排序的思想等。
"""

from cal_time import *
# 在定义函数前进行装饰
@timefn
#这是升序
def bubble_ascending_order(li,m):
  k=0
  while k <=m:
    for n in range(len(li)-1):#趟数
       exchange=False
       for i in range(len(li)-n-1):#无序区范围
           if li[i] > li[i+1]:
                li[i], li[i+1] = li[i+1], li[i]
                exchange=True
       if not exchange:#避免中途列表已经排序完成依然进行循环排序
           break
    k +=1
       # print("冒泡排序的过程:")
       # print(li)


print("请输入要查找的元素个数:",end="")
n=int(input())
li=[ i for i in range(10000)]
import random
random.shuffle(li)
print("--------------------------------------------------------------------------------------")
print("随机生成的列表为:",end="")
print(li)

print("------------------------------测试数据过大,需要等侯-------------------------------------")
bubble_ascending_order(li,n)
# print("-------------------------------该列表冒泡排序升序的结果为:---------------------------------")
# print(li)
print("------------------------------查找到最小的n个元素为:----------------------------------------")
print("[",end="")
for i in range(n+2):
    print(li[i],end=" , ")
print("]")

2.堆排序方法(Heap_Sort)

"""
作者:佩大奇
日期:2022/03/09/
描述:堆排序(不使用递归)
     堆排序主要使先建立堆,然后通过挨个出数的方法进行堆排序
速度:查找1000个需要时间:  0.04563 s
题目:
25. 查找最小的k个元素
【问题描述】
输出一组元素中的最小的k个元素。例如数据集为:{1、8、3、6、5、4、7、2},则最小的4个数字为1,2,3和4。
【基本要求】
由随机数产生测试数据,测试数据不小于10000个,测试k的不同取值对算法的影响,如k=10、50、100、500、1000、2000等;在课程设计文档中给出测试结果的表格。
多种算法实现,如借助选择排序、堆排序、快速排序的思想等。
"""
def sift(li,low,height):
   i=low#i移动父节点指针,一开始位于堆顶
   j=2*i+1#j移动子节点指针
   temp=li[low]#存放堆顶元素
   while j <=height:
        if j+1 <=height and li[j] <li[j+1]:
            j=j+1
        if li[j] >temp:
            li[i]=li[j]
            i=j#i指针移动下一层,即i指针移动至刚刚赋值后空缺位置的那一层
            j=2*i+1#j指针移动下一层
        else:
            li[i]=temp
            break
   li[i]=temp



from cal_time import *
# 在定义函数前进行装饰
@timefn
def heap(li):
    n=len(li)-1#节点个数
    #1.先建堆
    for i in range((n-1)//2,-1,-1):#这里是走父节点
        sift(li,i,n)
    # print("建立堆的结果:",end="")
     # print(li)没有孩子

    #2.挨个出数,成为有序序列
    for i in range(n,-1,-1):
        li[0] , li[i] =li[i] , li[0]
        sift(li,0,i-1)
    # print("堆排序的结果:",end="")
    # print(li)

print("请输入要查找的元素个数:",end="")
n=int(input())
li=[i for i in range(10000)]
import  random
random.shuffle(li)
print("--------------------------------------------------------------------------------------")
print("随机生成的列表为:",end="")
print(li)
# print("------------------------------测试数据过大,需要等侯-------------------------------------")
heap(li)
print("------------------------------查找到最小的n个元素为:----------------------------------------")
print("[",end="")
for i in range(n):
    print(li[i],end=" , ")
print("]")

3.插入排序方法(Insert_Sort)

"""
作者:佩大奇
日期:2022/03/06/
描述:插入排序:相当于扑克牌的插牌。
    无序区的元素i和有序区的元素比较,无序区开始位置的元素和有序区的所有元素比较,
    当无序区的开始位置比有序区中的某个元素小时,那么在所有比无序区开始元素大的有序区元素都向后移动一位,
    其中移动范围是有序区中的某个元素比无序区中的开始位置的元素小的位置的后一位开始到无序区的开始位置,
速度:需要时间: 查找1000个 4.45317 s
题目:
25. 查找最小的k个元素
【问题描述】
输出一组元素中的最小的k个元素。例如数据集为:{1、8、3、6、5、4、7、2},则最小的4个数字为1,2,3和4。
【基本要求】
由随机数产生测试数据,测试数据不小于10000个,测试k的不同取值对算法的影响,如k=10、50、100、500、1000、2000等;在课程设计文档中给出测试结果的表格。
多种算法实现,如借助选择排序、堆排序、快速排序的思想等。
"""

from cal_time import *
# 在定义函数前进行装饰
@timefn
def insert(li):
    for i in range(1,len(li)):#从无序区遍历
        j=i-1#有序区
        temp = li[i]
        while j>=0 and li[j]>temp:
            li[j+1]=li[j]
            j=j-1
        else:
            li[j+1]=temp
        # print("插入排序的过程为:",end="")
        # print(li)
    print("------------------------------插入排序的结果为---------------------------------------------")
    # print("插入排序的结果为:",end="")
    print(li)

print("请输入要查找的元素个数:",end="")
n=int(input())
li=[ i for i in range(10000)]
import random
random.shuffle(li)
print("--------------------------------------------------------------------------------------")
print("随机生成的列表为:",end="")
print(li)
print("------------------------------测试数据过大,需要等侯-------------------------------------")
insert(li)
print("------------------------------查找到最小的n个元素为:----------------------------------------")
print("[",end="")
for i in range(n):
    print(li[i],end=" , ")
print("]")

4.快速排序方法(Quick_Sort)

"""
作者:佩大奇
日期:2022/03/09/
描述:快速排序
速度:10000个数查找200个需要1.5秒,查找1000个需要时间: @timefn: partition took  1.70231 s,
     1100需要时间: @timefn: partition took  2.23899 s
题目:
25. 查找最小的k个元素
【问题描述】
输出一组元素中的最小的k个元素。例如数据集为:{1、8、3、6、5、4、7、2},则最小的4个数字为1,2,3和4。
【基本要求】
由随机数产生测试数据,测试数据不小于10000个,测试k的不同取值对算法的影响,如k=10、50、100、500、1000、2000等;在课程设计文档中给出测试结果的表格。
多种算法实现,如借助选择排序、堆排序、快速排序的思想等。
"""
from cal_time import *
# 在定义函数前进行装饰
@timefn
def partition(li,left,right):
   k=0
   i = left
   j = right
   if  i < j:#前提
         temple = li[left]
         while i < j:#循环次数
             while i < j and li[j] > temple:
                 j -=1
             if i < j :#避免第n次调用途中right全部值都小于temple,直到超过i的值才有小于temple的值
                 li[i] = li[j]
                 i +=1
             while i < j and li[i] < temple:
                 i +=1
             if i < j:
                 li[j]=li[i]
                 j -=1
         li[i]=temple
         partition(li,left,i-1)#递归调用
         partition(li,i+1,right)

print("请输入要查找的元素个数:",end="")
n=int(input())
li=[ i for i in range(10000)]
import random
random.shuffle(li)
print("--------------------------------------------------------------------------------------")
print("随机生成的列表为:",end="")
print(li)
partition(li,0,len(li)-1)
# print("快速排序的结果:",end="")
# print(li)
print("--------------------------------------------------------------------------------------")
print("------------------------------查找到最小的n个元素为:----------------------------------------")
print("[",end="")
for i in range(n+2):
    print(li[i],end=" , ")
print("]")

5.选择排序方法(Select_Sort)

"""
作者:佩大奇
日期:2022/03/05/
描述:选择排序:每遍历一次都能找到一个最小的值,每次查找后,将最小值放在第一位,第二个最小值放在第二位,以此类推,当查找到k个元素时停止查找
特点:速度快,10000个数里查200个仅需0.13秒,查找1000个需要时间:  0.77154 s

题目:
25. 查找最小的k个元素
【问题描述】
输出一组元素中的最小的k个元素。例如数据集为:{1、8、3、6、5、4、7、2},则最小的4个数字为1,2,3和4。
【基本要求】
由随机数产生测试数据,测试数据不小于10000个,测试k的不同取值对算法的影响,如k=10、50、100、500、1000、2000等;在课程设计文档中给出测试结果的表格。
多种算法实现,如借助选择排序、堆排序、快速排序的思想等。 
"""

from cal_time import *
# 在定义函数前进行装饰
@timefn
def select(li,m):
   n=m
   if n >len(li):
       print("你要查找的元素个数有误")
   else:
       for i in range(n):#无序区的开始位置(范围就是整个列表)
           for j in range(i+1,len(li)):
               if li[i] > li[j]:
                   li[i] ,li[j] = li[j] , li[i]



print("请输入要查找的元素个数:",end="")
m=int(input())
li=[ i for i in range(10000)]
import random
random.shuffle(li)
print("--------------------------------------------------------------------------------------")
print("随机生成的列表为:",end="")
print(li)
print("------------------------------测试数据过大,需要等侯-------------------------------------")
select(li,m)
print("------------------------------查找到最小的n个元素为:----------------------------------------")
print("[",end="")
for i in range(m+2):
    print(li[i],end=" , ")
print("]")
# print(li)

6.其他方法1(Other_demo1)

"""
作者:佩大奇
日期:2022/03/10/
描述:剩下元素遍历一边就可以查找到所有元素
缺点:速度贼慢,查找30个数据要45秒
"""
def  quick_sort(li,i,n2):#快速排序一小部分,i是起始位置,n2是查找元素的列表长度
    # k=n2 #要查找的个数
    left=i#指针
    right=n2#指针

    if left<right:
      temp=li[i]
      while left<right:
        while right>left and li[right]>=temp:
            right -=1
        if left <right:
                li[left]=li[right]
                left +=1
        while left <right and li[left] <=temp:
            left +=1
        if left <right:
                li[right]=li[left]
                right -=1
      li[left]=temp
      quick_sort(li,0,left-1)
      quick_sort(li,left+1,n2)



# def sort(li,left,right):
#     a=left#指针
#     b=right#指针
#     if a<b:
#         temps=li[b]
#         mid=(a+b)//2
#         while mid>a and li[mid] >=temps:
#             mid -=1
#         if mid==a and li[mid]>temps:
#             for s in range(b-1,-1,-1):
#                 if s==mid:
#                   li[s+1]=temps
#         if li[mid] < temps and li[mid+1] >=temps:
#             for s in range(b-1,-1,-1):
#                 if s==mid:
#                   li[s+1]=temps
#                   break
#
#
#         while mid <=b and li[mid] <temps:
#             mid +=1
#         if li[mid] < temps and li[mid+1] >=temps:
#             for s in range(b-1,-1,-1):
#                 li[s+1]=li[s]
#                 if s==mid:
#                   li[s+1]=temps
#                   break

from cal_time import *
# 在定义函数前进行装饰
@timefn
def other_search(li,cleft,dright,number):#cleft是其实位置,deright是列表总长度,number是要查找元素个数,用于确定顺序表最后的位置
     count=number#元素个数
     j=cleft#指针
     g=number-1#顺序指针
     h=number#指针

     while h<=len(li)-1:
         if li[h]<li[g]:
            li[h], li[g]=li[g],li[h]
            # sort(li,0,number-1)
            quick_sort(li,0,g)
         h +=1
     for t in range(number):
         print(li[t],end=" ")
     print()

li=[i for i in range(10000 )]
import random
random.shuffle(li)
print("随机生成的列表位:",end=" ")
print(li)
print("请输入你要查找的元素个数:",end="")
n=int(input())
print("列表中前n个元素为:",end=" ")
for i in range(n):
    print(li[i],end=" ")
print()
print("---------------")
quick_sort(li,0,n-1)
print(li)
print("---------查找结果:--------")
other_search(li,0,len(li)-1,n)

7.其他方法2(可能是修改的堆排序)(Other_Sort)

"""
作者:佩大奇
日期:2022/03/12/
描述:堆排序(不使用递归)
     堆排序主要使先建立堆,然后通过挨个出数的方法进行堆排序,当输出的数等于k是,停止查找输出
速度:快,10000个数中查找500个最小数仅需0.00225秒


题目:
25. 查找最小的k个元素
【问题描述】
输出一组元素中的最小的k个元素。例如数据集为:{1、8、3、6、5、4、7、2},则最小的4个数字为1,2,3和4。
【基本要求】
由随机数产生测试数据,测试数据不小于10000个,测试k的不同取值对算法的影响,如k=10、50、100、500、1000、2000等;在课程设计文档中给出测试结果的表格。
多种算法实现,如借助选择排序、堆排序、快速排序的思想等。
"""
def sift(li,low,height):
   i=low#i移动父节点指针,一开始位于堆顶
   j=2*i+1#j移动子节点指针
   temp=li[low]#存放堆顶元素
   while j <=height:
        if j+1 <=height and li[j] >li[j+1]:
            j=j+1
        if li[j] <temp:
            li[i]=li[j]
            i=j#i指针移动下一层,即i指针移动至刚刚赋值后空缺位置的那一层
            j=2*i+1#j指针移动下一层
        else:
            li[i]=temp
            break
   li[i]=temp




from cal_time import *
# 在定义函数前进行装饰
@timefn
def heap(li,t):
    n=len(li)-1#节点个数
    #1.先建堆
    for i in range((n-1)//2,-1,-1):#这里是走父节点
        sift(li,i,n)
    # print("建立堆的结果:",end="")
     # print(li)没有孩子

    #2.挨个出数,成为有序序列
    # k=0
    for i in range(n,-1,-1):
      if i>=len(li)-1-t:
        li[0] , li[i] =li[i] , li[0]
        sift(li,0,i-1)
        # k +=1
    # print("堆排序的结果:",end="")
    # print(li)

print("请输入要查找的元素个数:",end="")
n=int(input())
li=[i for i in range(10000)]
import  random
random.shuffle(li)
print("--------------------------------------------------------------------------------------")
print("随机生成的列表为:",end="")
print(li)
# print("------------------------------测试数据过大,需要等侯-------------------------------------")
heap(li,n-1)
# print(li)
print("------------------------------查找到最小的n个元素为:----------------------------------------")
print("[",end="")
for i in range(len(li)-1,len(li)-1-n-2,-1):
    print(li[i],end=" , ")
print("]")


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

9个9青蛙场

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值