python列表输入10个数、并排序-我该如何对一百万个数字进行排序,并且仅在Python中打印前十个数字?...
我有一个包含一百万个数字的文件。 我需要知道如何有效地对其进行排序,以免使计算机停滞不前,并且仅打印前十名。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#!/usr/bin/python3
#Find the 10 largest integers
#Don"t store the whole list
import sys
def fOpen(fname):
try:
fd = open(fname,"r")
except:
print("Couldn"t open file.")
sys.exit(0)
all = fd.read().splitlines()
fd.close()
return all
words = fOpen(sys.argv[1])
big = 0
g = len(words)
count = 10
for i in range(0,g-1):
pos = i
for j in range(i+1,g):
if words[j] > words[pos]:
pos = j
if pos != i:
words[i],words[pos] = words[pos],words[i]
count -= 1
if count == 0:
print(words[0:10])
我知道这是选择排序,我不确定什么是最好的排序。
这是作业吗? 还是一本书中的练习?
它的功课..
这显然是一个XY问题。 问题不是排序,而是找到十个最大的整数。 尽管可以通过首先排序然后选择前十个条目来找到它们,但这并不是最佳解决方案。 最好的解决方案是百事可乐提供的解决方案。
我不会说百事可乐的解决方案是"最好的",也许是第一个现有的解决方案。 实际上,他实际上没有提供任何有效的代码,但确实表明这是一个XY问题。
如果只需要前10个值,那么您将浪费大量时间对每个数字进行排序。
只需浏览数字列表,并跟踪到目前为止看到的前10个最大值。在浏览列表时更新前十名,并在到达末尾时将其打印出来。
这意味着您只需要对文件进行一次遍历(即theta(n)的时间复杂度)
一个更简单的问题
您可以将您的问题看成是在数字列表中找到最大值的概括。如果给出{2,32,33,55,13, ...}并被要求找出最大值,那么您会怎么做?典型的解决方案是浏览列表,同时记住迄今为止遇到的最大数字,并将其与下一个数字进行比较。
为了简单起见,让我们假设我们正在处理正数。
1
2
3
4
5
6
7
8Initialize max to 0
0 < 2, so max = 2
2 < 32, so max = 32
32 < 33, so max = 33
33 < 55, so max = 55
55 > 13, so max = 55
...
return max
如此看来,我们可以在列表的单个遍历中找到最大值,这与任何类型的比较排序相反。
泛化
在列表中查找前10个值非常相似。唯一的区别是,我们需要跟踪前10名,而不只是最大值(前1名)。
底线是您需要一些容纳10个值的容器。当您遍历庞大的数字列表时,在大小为10的容器中关心的唯一值是最小值。这是因为,如果您发现了一个新号码,该号码应该排在前十名之内,那么它将被替换。
无论如何,事实证明最适合快速找到分钟的数据结构是一个最小堆。但是我不确定您是否了解堆,而将堆用于10个元素的开销可能会超过其好处。
任何容纳10个元素并可以在合理的时间内获得最小值的容器都是一个好的开始。
这确实有可能会慢10倍,这可能意味着10毫秒而不是1毫秒。但这可能意味着10秒而不是1秒。
如果您想获得前K个值,则为O(KN)(取决于您如何跟踪前10个值),请查看en.wikipedia.org/wiki/Selection_algorithm,诸如中位数的中值为O(N )
@robertking:在OPs问题中,k给出为常数10,这就是为什么我将其简化为theta(n)的原因。如果我们实际上关心前k个值的通用算法,则可以使用大小为k的堆来跟踪前k个值,将其减少为theta(n * lg(k))。这可能也是heapq所做的。但是谁知道呢,也许管理堆的开销大于遍历大小为10的数组的开销。您必须对其进行概要分析才能找到答案。
真正。我喜欢您的答案表明不需要对整个列表进行排序。但是,"仅追踪前十大价值"并不像我认为的那么容易。更简单地说,可以只取列表中的最小值,然后弹出最小值。这样做十次,可能会很快。
抱歉,我仍在学习CS等算法。需要简要说明一下如何处理100万个数字中的10个吗?
@pepsi:堆解决方案也不是最佳方案。与k无关,选择为O(n)。
@NeilG请参阅我的选择方法答案。
@NeilG:的确如此,但是请记住在处理大文件中的数字时,OP代码中有一条注释,内容为"不要存储整个列表"。此处给出的方法只对文件进行一次遍历,这意味着不需要立即将整个文件读入内存。另外,文件是顺序读取的,这利用了顺序磁盘IO比随机磁盘快得多的事实。鉴于IO很可能成为瓶颈,因此这一点很重要。
@robertking:您和larsmans是我支持的答案。
@pepsi:注意指出不存储整个内容的注释(尽管一百万个数字实际上并不是一个"大文件"),这是一个好主意。没错,您的解决方案只需执行一次连续遍历。但是," quickselect"也将顺序地而不是随机地访问文件(但是它通常需要多次通过)。
@NeilG我的意思是我的其他答案。我做了两个回答:P
最好的排序是部分排序,在Python库中可以作为heapq.nlargest使用。
这样,您就拥有了一个漂亮的O(n)解决方案,而不是一个O(nlogn)
@ julio.alegria:和O(1)内存。
最好的事情是:您可以提供键功能,就像sorted一样。
1
2
3
4
5
6
7
8
9
10import heapq
with open("nums.txt") as f:
numbers=map(int,f.readlines())
print heapq.nlargest(10,numbers)
print heapq.nsmallest(10,numbers)
"""
[1132513251, 13252365, 23512, 2000, 1251, 1235, 324, 100, 82, 82]
[1, 1, 7, 13, 15, 21, 22, 22, 33, 82]
"""
谢谢罗伯特,这是我的解决方案。一百万个单词,只需要大约4秒钟。谢谢!
嗯,我原以为会更快。也许您的IO比我的慢。无论如何,readlines()应该是读取行的最快方法,这可能是这里的瓶颈。随意支持其他解决方案或给绿色勾号
@SethRainerKania只是让您知道,python内置解决方案可能不是您的老师正在寻找的解决方案,并且可能不会给您任何帮助。
虐待考虑到这一点。至少在研究新答案时,我有正确的前10名。
我建议您阅读:en.wikipedia.org/wiki/Selection_algorithm另请注意O(N)和O(KN)之间的区别
创建数字列表的首选方法是numbers = map(int, f)。这样可以避免将整个文件内容存储在内存中(也可以节省一些键入内容)。
谢谢斯文。那将是我的首选方式,尤其是在文件较大的情况下。
您想要的是一个好的选择算法
以下python代码基于功能partition()
分区将列表分为两部分。小于" pivotValue"的值将移动到列表的开头。大于ivotValue的值将移动到列表的末尾。
在O(N)操作中,这是通过从头到尾遍历列表来完成的,每次查看一个值时,它都会将其移动到列表的开头附近(仅当它小于枢轴值时)。
(请注意,在您的情况下,我们实际上将较大的值移到列表的开头,因为您想要最大的值而不是最小的值)。
一旦我们以O(N)时间对列表进行了分区,则在列表开始处剩下m个大数字。如果m = 10则很好,那就是您的十个最大数字。如果m大于10,则需要再次对m个最大数进行划分,以从m个最大数中获得10个最大数。如果m小于10,则我们需要再增加10-m个数字,因此我们将右边的部分划分为10-m个数字,并将它们添加到我们的m个数字中以获得所需的10个数字。
因此,我们一直进行分区,直到有10个最大的数字。这是通过select()方法完成的。整个方法通常非常快,因为每次执行分区时,我们剩下的数量大约要处理一半。 (如果您不断将需要查看的数字数除以2,那就很好了)。每次我们创建一个产生10个以上大数字的分区时,我们都会忽略整个数字堆,这些数字太小了。
这是代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44def partition(_list,left,right,pivotIndex):
pivotValue=_list[pivotIndex]
_list[right],_list[pivotIndex]=pivotValue,_list[right]
storeIndex=left
for i in range(left,right):
if _list[i] > pivotValue:
_list[storeIndex],_list[i]=_list[i],_list[storeIndex]
storeIndex+=1
_list[right],_list[storeIndex]=_list[storeIndex],_list[right]
return storeIndex
from random import randint
def select(_list,left,right,k):
if left==right:
return _list[:left+1]
pivotIndex=randint(left,right)
pivotNewIndex=partition(_list,left,right,pivotIndex)
pivotDist=pivotNewIndex-left+1
if pivotDist==k:
return _list[:pivotNewIndex+1]
elif k
return select(_list,left,pivotNewIndex-1,k)
else:
return select(_list,pivotNewIndex+1,right,k-pivotDist)
_list=[1,2,109,2234,23,6,1,234,11,4,12451,1]
left=0
right=len(_list)-1
pivotIndex=4
print _list
"[1, 2, 109, 2234, 23, 6, 1, 234, 11, 4, 12451, 1]"
print partition(_list,left,right,pivotIndex) #partition is order(N).
"7" #index 7, so the lowest number are in the first 7 numbers of the list [1, 2, 1, 6, 1, 11, 4, 23]
print _list
"[1, 2, 1, 6, 1, 11, 4, 23, 2234, 109, 12451, 234]"
print select(_list,left,right,10)
"[1, 2, 1, 1, 4, 11, 6, 23, 109, 234]"
with open("nums.txt") as f:
numbers=map(int,f.readlines())
print select(numbers,0,len(numbers)-1,10)
"[1132513251, 2000, 23512, 13252365, 1235, 1251, 324, 100, 82, 82]"
真好虽然,您可能应该返回切片而不是复制列表,并且如果遵循pep 8,则代码将更易于阅读
感谢@NeilG Im立即阅读pep 8。
python列表输入10个数、并排序-我该如何对一百万个数字进行排序,并且仅在Python中打印前十个数字?...相关推荐
- python一次性输入10个数_python如何一次性输入多个数
python一次性输入多个数的方法:1.输入两个数字[m, n = map(int, input().split());]:2.输入三个及三个以上数字[a, b, c, d = map(int, in ...
- c语言找出最大值和最小值并按降序排输出,C语言用排序法给十个数降序排列,用C语言编写,输入10个数按降序排列...
问题标题 C语言用排序法给十个数降序排列,用C语言编写,输入10个数按降序排列 2019-6-4来自ip:14.161.145.86的网友咨询 浏览量:562 手机版 问题补充: C语言用排序法给十个 ...
- c语言中输入大数,如何使用C语言实现输入10个数按从大到小的顺序排序输出
本文主要向大家介绍了如何使用C语言实现输入10个数按从大到小的顺序排序输出,通过具体的内容向大家展示,希望对大家学习C语言有所帮助. 用选择排序法编写c语言,实现从键盘上输入10个数,按从大到小的顺序 ...
- 10个数冒泡排序法c语言代码,输入10个数用冒泡法排序
输入10个数,用冒泡排序法按由小到大顺序排序并输如下参考: #包括< stdio, h > Intmain() { Inta[10]={0}: IntI=0,j=0,t=0: For (I ...
- ACMNO.37 C语言-数字交换 输入10个整数,将其中最小的数与第一个数对换,然后把最大的数与最后一个数对换。写三个函数; ①输入10个数;②进行处理;③输出10个数。
题目描述 输入10个整数,将其中最小的数与第一个数对换,然后把最大的数与最后一个数对换. 写三个函数: ①输入10个数:②进行处理:③输出10个数. 输入 10个整数 输出 整理后的十个数,每个数后跟 ...
- c语言输入10个数从小,C语言中,从键盘输入10个数,从小到大排列输出,怎
公告: 为响应国家净网行动,部分内容已经删除,感谢读者理解. 话题:C语言中,从键盘输入10个数,从小到大排列输出,怎么写啊,最好注回答:#includestdio.h void swap(int * ...
- python怎么算数据平均数,python怎样求10个数的平均数
python怎样求10个数的平均数 发布时间:2021-03-12 09:18:47 来源:亿速云 阅读:100 作者:小新 这篇文章主要介绍了python怎样求10个数的平均数,具有一定借鉴价值,感 ...
- (C++)输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。要求用3个函数实现,分别为输入10个数、进行处理、输出10个数。要求使用指针的方法进行处理。
#include<cstdio> //输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换.要求用3个函数实现,分别为输入10个数.进行处理.输出10个数.要求使用指针 ...
- C语言学习之输入10个数,输出其中最大的一个数。
输入10个数,输出其中最大的一个数. #include <stdio.h> void main(){int a[10],max=0;printf("请输入十个整数:\n" ...
最新文章
- 支付宝技术风险负责人陈亮:把事情做到极致,技术的差异性才会体现出来
- 信号公式汇总之傅里叶变换
- django解决跨域问题
- Elasticsearch forceMerge操作
- DeepMind用ReinforcementLearning玩游戏
- 指定Gradle构建属性
- html css3模拟心的跳动
- ASP.NET 网站项目 EF 的简单操作例子
- CCNA training notes
- C# 无边框异型窗体制作
- android开发学习笔记系列(1)-android起航
- 国外计算机应用基础,计算机应用基础试题(国外英文资料).doc
- PPT文件怎么快速压缩?
- 西安交通大学保研面试题
- 基于SOA的设备智能维护系统架构设计及实现
- oracle卸载步骤图解,Oracle完全卸载步骤
- 知道生产日期和保质期来计算有效期至的方法和代码
- 苹果手机点击输入框input 页面放大 超出屏幕问题
- 企业“招投标”一般需要办理哪些体系认证?
- 英语计算机单词怎么记,英语单词快速记忆法