我有一个包含一百万个数字的文件。 我需要知道如何有效地对其进行排序,以免使计算机停滞不前,并且仅打印前十名。

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中打印前十个数字?...相关推荐

  1. python一次性输入10个数_python如何一次性输入多个数

    python一次性输入多个数的方法:1.输入两个数字[m, n = map(int, input().split());]:2.输入三个及三个以上数字[a, b, c, d = map(int, in ...

  2. c语言找出最大值和最小值并按降序排输出,C语言用排序法给十个数降序排列,用C语言编写,输入10个数按降序排列...

    问题标题 C语言用排序法给十个数降序排列,用C语言编写,输入10个数按降序排列 2019-6-4来自ip:14.161.145.86的网友咨询 浏览量:562 手机版 问题补充: C语言用排序法给十个 ...

  3. c语言中输入大数,如何使用C语言实现输入10个数按从大到小的顺序排序输出

    本文主要向大家介绍了如何使用C语言实现输入10个数按从大到小的顺序排序输出,通过具体的内容向大家展示,希望对大家学习C语言有所帮助. 用选择排序法编写c语言,实现从键盘上输入10个数,按从大到小的顺序 ...

  4. 10个数冒泡排序法c语言代码,输入10个数用冒泡法排序

    输入10个数,用冒泡排序法按由小到大顺序排序并输如下参考: #包括< stdio, h > Intmain() { Inta[10]={0}: IntI=0,j=0,t=0: For (I ...

  5. ACMNO.37 C语言-数字交换 输入10个整数,将其中最小的数与第一个数对换,然后把最大的数与最后一个数对换。写三个函数; ①输入10个数;②进行处理;③输出10个数。

    题目描述 输入10个整数,将其中最小的数与第一个数对换,然后把最大的数与最后一个数对换. 写三个函数: ①输入10个数:②进行处理:③输出10个数. 输入 10个整数 输出 整理后的十个数,每个数后跟 ...

  6. c语言输入10个数从小,C语言中,从键盘输入10个数,从小到大排列输出,怎

    公告: 为响应国家净网行动,部分内容已经删除,感谢读者理解. 话题:C语言中,从键盘输入10个数,从小到大排列输出,怎么写啊,最好注回答:#includestdio.h void swap(int * ...

  7. python怎么算数据平均数,python怎样求10个数的平均数

    python怎样求10个数的平均数 发布时间:2021-03-12 09:18:47 来源:亿速云 阅读:100 作者:小新 这篇文章主要介绍了python怎样求10个数的平均数,具有一定借鉴价值,感 ...

  8. (C++)输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。要求用3个函数实现,分别为输入10个数、进行处理、输出10个数。要求使用指针的方法进行处理。

    #include<cstdio> //输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换.要求用3个函数实现,分别为输入10个数.进行处理.输出10个数.要求使用指针 ...

  9. C语言学习之输入10个数,输出其中最大的一个数。

    输入10个数,输出其中最大的一个数. #include <stdio.h> void main(){int a[10],max=0;printf("请输入十个整数:\n" ...

最新文章

  1. 支付宝技术风险负责人陈亮:把事情做到极致,技术的差异性才会体现出来
  2. 信号公式汇总之傅里叶变换
  3. django解决跨域问题
  4. Elasticsearch forceMerge操作
  5. DeepMind用ReinforcementLearning玩游戏
  6. 指定Gradle构建属性
  7. html css3模拟心的跳动
  8. ASP.NET 网站项目 EF 的简单操作例子
  9. CCNA training notes
  10. C# 无边框异型窗体制作
  11. android开发学习笔记系列(1)-android起航
  12. 国外计算机应用基础,计算机应用基础试题(国外英文资料).doc
  13. PPT文件怎么快速压缩?
  14. 西安交通大学保研面试题
  15. 基于SOA的设备智能维护系统架构设计及实现
  16. oracle卸载步骤图解,Oracle完全卸载步骤
  17. 知道生产日期和保质期来计算有效期至的方法和代码
  18. 苹果手机点击输入框input 页面放大 超出屏幕问题
  19. 企业“招投标”一般需要办理哪些体系认证?
  20. 英语计算机单词怎么记,英语单词快速记忆法

热门文章

  1. python2 安装 MySQL-python
  2. python colorama模块
  3. 动态SQL和PL/SQL的EXECUTE选项分析
  4. Laravel 在Centos上的安装
  5. 巧用自媒体平台,让你事半功倍
  6. 经典的机器学习方面源代码库(非常全,数据挖掘,计算...)
  7. 【转载】SQL 模糊查询
  8. 飞鸽传书2007的java学习感想
  9. C++高手总结的编程规律
  10. 干得最多最累,工资还不如新人