编程珠玑第一章习题6.1000个整数排序

题目描述: 1~1000万的整数,随机挑出1000个整数(可重复),每个整数最多可以出现10次。将这些整数按照升序排序。

分析:      1000个整数,我们可以用1000万个字符按大小来记录它出现的次数,如同 3, 1, 5, 6,5  用5个字符数组表示就是 { 1, 0, 1, 0, 2, 1}。1出现1次,所以第一个字符就用1记录;2出现0次,用0记录,以此类推。

然后,我们按从左往右的顺序,第 i 索引的字符是多少,就输出多少遍该索引(索引即是你要输出的整数)。输出结果是:1,3,5,5,6。是不是很魔性。这种存储完毕即有序的排序,时间复杂度位 O(N),空

间复杂度就看用什么来存储了。

  既然可以这样的话,我们可以用位图来存储它,可以节约很多空间,而且位操作的速度也很快。可以考虑用每一位记录一个整数,但是位只能是0或1,出现的次数最多能记录一次,要是最多出现10次的话,最少

要4位(二进制表示 BIN 1111,   十进制 DEC 15)。所以,我们可以用半字节来记录一个整数,那么,1000万个整数,需用(1000万/2)500万个字节。在java中用int型来存储,需要(500万/4)125万个int型就可以了。

是不是比1000个字符节省了很多的空间(尽管这些空间在现在不算什么)。但是我们还是要有优化精神。

准备1:既然要用位来记录整数,就必须了解位的相关操作与运算。我们可以用两种方式来实现位的加法。

首先来科普一下,位的加法运算,以四位为例。

(1)位的加法可以用异或位运算来完成:BIN (0001) + BIN (0001)  = BIN (0001)  ^ BIN(0001)  =  BIN (0001),注意此时的结果是不带进位的和。

(2)位加法的进位的计算可以用位的与运算来完成:进位 = [ BIN (0001)  & BIN (0001) ] << 1  = BIN (0010)。

(3)然后将(1)和(2)再相加得到的结果就是 最终的和:BIN (0001)  +  BIN (0010) =  BIN (0001)  ^ BIN(0010)  +  [ BIN (0001)  & BIN (0001) ] << 1

现在我们来看,最终和又变成了两个二进制相加了,那加到什么时候才停止呢,肯定是加到没有进位了呀,就是进位等于0啊。

是不是感觉豁然开朗,这不就是一个递归相加操作嘛,直到进位等于0就结束递归。那心里有低了,我们完全可以用递归来实现这一加法操作(真是一波操作猛如虎啊)。

那我们来实现它一下吧。

就几行代码,是不是很简单。

准备2:开始动手编码前,我们首先应该清楚实现位结构存储需要哪些API,就是把某整数按半字节存储到按整型数组里,然后再根据记录的数值循环输出 这一系列操作的基本函数是什么。

1.  set函数:把某个整数的出现次数存储到 int中。halfSet( int  val )

2.  clear函数: 把某个整数的出现次数清零。此操作可以初始化我们的 int数组,还可以干其他的活(后面讲)。halfClr( int val )

3.  getValue函数:把某个整数的出现次数获取出来,以便循环输出。 getValue( int  val )

    下面我们就着手大干一场吧。。

实现:

dfd

原文地址:https://www.cnblogs.com/leafIcesun/p/11980112.html

时间: 2024-10-18 13:17:14

编程珠玑第一章习题6.1000个整数排序的相关文章

编程珠玑第一章习题

第一章习题1解析 以下代码均使用MSVC 6.0编译运行通过,为了便于学习,在原代码的基础上进行了一定的修改. 1.如何使用一个具有库的语言来实现一种排序算法以表示和排序集合,将代码实现可用 1 #include<stdio.h> 2 #include<stdlib.h> 3 int comp(const void *x,const void *y){ 4 return (*(int*)x-*(int*)y); 5 } 6 int a[5]={45,25,64,10,4}; 7 v

编程珠玑第一章习题答案

习题 1.1      如果不缺内存,如何使用一个具有库的语言来实现一种排序算法? 因为C++有sort,JAVA也有,这里以C++为例给出,记住如果用set集合来排序时,是不可以有元素重复的 代码: #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <list> #include <

编程珠玑——第一章习题

1.如果不缺内存,如何使用一个具有库的语言来实现以后总排序算法和排序集合? 答:这个不同语言有不同的库函数排序C有qsort,java有sort排序,具体就不贴代码了.C++有实现排序的库函数:sort,该函数的实现是快速排序.另外C++的容器Map和set均可以实现排序.由于Map和set的实现是红黑树,所以具有自动排序功能. 2.如何使用位逻辑运算(如与.或.移位)来实现位向量? 这个道题的核心就在于想要把某bit置0,将该位直接和0做与操作,想要保持某bit位不变,将该位与1做与操作,想要

编程珠玑 第一章

题目:一个最多包含n个正整数的文件,每个数都小于n,其中n=10^7,且所有正整数都不重复.求如何将这n个正整数升序排列. 约束:最多有1MB的内存空间可用,有充足的磁盘存储空间. 习题2 习题3 实现位向量用于排序. #include<stdio.h> #define N 10000000 #define Shift 5 #define BitPerWord (sizeof(int)*8) #define Mask ((1<<Shift)-1) int a[1+N/BitPerW

稀疏集:编程珠玑第一章第九题

<Programming Pearls> solutions for Column 1中的第9题题解 关键字: Sparse set 原题: The effect of  initializing the vector data[0..n-1] can be accomplised with a signature contained in two additional n-element vectors, from and to ,and an integer top. If the ele

编程珠玑第一章中的代码

使用位图法对七位正整数进行排序的算法. #include <stdio.h> #include <stdlib.h> #include <time.h> #define BITSPERWORD 32 #define SHIFT 5 #define MASK 0x1F #define N 100 int a[1 + N/BITSPERWORD]; /* * i >> SHIFT :i / (1 << SHIFT) 即i / (1 <<

一维向量旋转算法 编程珠玑 第二章

看了编程珠玑第二章,这里面讲了三道题目,这里说一下第二题,一维向量旋转算法. 题目:将一个n元一维向量(例数组)向左旋转i个位置. 解决方法:书上讲解了5种方法,自己只想起来2种最简单方法(下面讲的前两种). 1.原始方法. 从左向右依次移动一位,对所有数据平移:这样循环i次,算法最坏时间复杂度达n^2.耗时不推荐. 2.空间换时间. 顾名思义,申请一个i长度的空间,把前i半部分放到申请空间中,再把后面的所有数据向左移动i个位置,最后把申请的空间中的数据放到后半部分.浪费空间,不推荐. 3.杂技

编程珠玑第二章

编程珠玑第二章 A题 给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中一32位整数. 1.在文件中至少存在这样一个数? 2.如果有足够的内存,如何处理? 3.如果内存不足,仅可以用文件来进行处理,如何处理? 答案: 1.32位整数,包括-2146473648~~2146473647,约42亿个整数,而文件中只有40亿个,必然有整数少了. 2.如果采用位数思想来存放,则32位整数最多需要占用43亿个位.约512MB的内存空间. 可以采用前一章的位处理方法.然后判断每个in

Functional Programming Principles in ScalaScala函式编程原理 第一章笔记

所有non-trival编程语言都提供了 基本表达式(expression)去表示最简单的表达式 组合表达式的方法 抽象表达式的方法,也就是为表达式引入一个名字去引用它 substitional model 替代模型 sumOfSquares(3,2+2) sumOfSquares(3,4) square(3)+square(4) 9+square(4) 9+16 25 这种模型的核心概念是所有的表达式都规约成值,替代模型在lamada表达式中被形式化,构成了函数式编程的基石 substitio