排序算法总结之位排序(一)
2014-03-31 22:04
225 查看
最近在看一本计算机经典著作《编程珠玑 第2版》,第一章开篇谈到怎样在内存有限的情况下给一个磁盘文件排序,文中使用到了位向量来解决此问题,本人菜鸟觉得此方法很经典,遂在此总结一下,方便日后查阅。
所谓位排序,即是将位向量中的每一位与一个待排序的整数相关联,位向量中待排序整数值的位置1,位向量的位数大于等于待排序整数的最大值,如:要对13, 9, 15, 8, 3,,12,7进行排序,则可以使用一个16位的位向量1011 0011 1000 1000来对这些要排序的整数进行标识,即:第3位(从0开始)的1代表要排序的整数3,第7位的1代表待排序的整数7....。标识完后,然后通过一个迭代对位向量的每一位(从左到又,或从右到左)进行判断,如果为1,即输出当前的迭代值(即为待排序的整数值),迭代完成后输出的序列即为排序后的序列。
要实现位排序,需要以下三个步骤:
1、首先实现一个位向量;
2、将待排序整数序列映射到位向量;
3、迭代判断位向量的每一位(从左到右或从右到左),如果为1,则输出当前迭代值(即为待排序的整数值)。
1、位向量的实现:
即实现位向量的置位、清零、判断这3个操作。
/--------------------------------------------------------.h 文件------------------------------------------------------------------------------------------/
/-----------------------------------------------------------------------------------------.cpp文件-----------------------------------------------------------------------------------------------------/
/---------------------------------------------------------------------------------主程序------------------------------------------------------------------------------------------/
data.txt
267 242
25 153
149 16
227 278
147 73
166 61
229 287
68 113
243 163
216 225
185 186179
19479
34 250
8 140162
217 54
63 156
7 241 95142
264112
83 19 215173
71 284
182 265
274 143
59 236
121 14
76 270
206 187
100 210
167 11
290 191
152 1 102134
150281
96 124
58 223
200 26
172 86
292 282
188 239
271 82
145 131
137 120
75 181
87 154
24 203
256 161
115 109
234 48
174 226
13 2 12629
285 232
28 222
17 158
35 169
51 273
5 66 20798
93 272
70 62 16874
81 6
9 246
253 40
104 53132
94 32
248 133
240
55 238
297 25123
204 171
31
105266
datasorted.txt
1 2
5 6 78
9 11
13 14
16 17 1923
24 25
26 2829
31
32 34 3540
48 51
53 5455
58
59 61 6263
66 68
70 7173
74
75 76 7981
82 83
86 8793
94
95 96 98100
102104
105109
112113
115 120
121 124
126 131
132 133
134 137
140 142
143 145
147 149
150 152
153 154
156 158
161 162
163 166
167 168
169 171
172 173
174 179
181 182
185 186
187 188
191 194
200 203
204 206
207 210
215 216
217 222
223 225
226 227
229 232
234 236
238 239
240 241
242 243
246 248
250 251
253 256
264 265
266 267
270 271
272 273
274 278
281 282
284 285
287 290
292 297
所谓位排序,即是将位向量中的每一位与一个待排序的整数相关联,位向量中待排序整数值的位置1,位向量的位数大于等于待排序整数的最大值,如:要对13, 9, 15, 8, 3,,12,7进行排序,则可以使用一个16位的位向量1011 0011 1000 1000来对这些要排序的整数进行标识,即:第3位(从0开始)的1代表要排序的整数3,第7位的1代表待排序的整数7....。标识完后,然后通过一个迭代对位向量的每一位(从左到又,或从右到左)进行判断,如果为1,即输出当前的迭代值(即为待排序的整数值),迭代完成后输出的序列即为排序后的序列。
要实现位排序,需要以下三个步骤:
1、首先实现一个位向量;
2、将待排序整数序列映射到位向量;
3、迭代判断位向量的每一位(从左到右或从右到左),如果为1,则输出当前迭代值(即为待排序的整数值)。
1、位向量的实现:
即实现位向量的置位、清零、判断这3个操作。
/--------------------------------------------------------.h 文件------------------------------------------------------------------------------------------/
#ifndef _CBITMAP_H_ #define _CBITMAP_H_ #define BITPERWORD 32 // 本例使用整形数组实现位向量,整形占4byte=32bit #define SHIFT 5 // 判断当前要置位或清零的位位于哪个数组中,即确定数组的下标 #define MASK 0x1F // 置位清零掩码,cpp文件中将对将对该掩码进行说明 class CBitMap { // construct、deconstruc public: CBitMap(unsigned int BitNum); ~CBitMap(); public: int *a; // 位向量指针 public: void set(int i); // 位向量第i位置1 void clr(int i); // 位向量第i位清0 bool test(int i); // 位向量第i位是否为1,是,返回TRUE,否,返回FALSE }; #endif
/-----------------------------------------------------------------------------------------.cpp文件-----------------------------------------------------------------------------------------------------/
#include "stdafx.h" #include <memory> #include "CBitMap.h"
// BitNum: 待排序整数的最大值
CBitMap::CBitMap(unsigned int BitNum) { a = new int [BitNum/BITPERWORD + 1]; // 将整形数组看成一个位向量 假设待排序的整数的最大值为100,则100/32+1 = 4,即用数组a[4](共128位)即 可表示所有待排序的整数,其中a[0]代表低32位,a[1]代表次低32位,a[2]代表次高32位,a[3]代表高32位。 } CBitMap::~CBitMap() { delete []a; a = NULL; }
// 将位向量第i位置1 void CBitMap::set(int i) { a[i>>SHIFT] |= (1<<(i&MASK)); // i>>SHIFT===> i>>5 <===> i/32,即判断第i位在数组中的下标。i&MASK===>i&0x1f <===> i%32,如:i=25,则
i&0x1f = 0001 1001 = 25,当i<=31时,i&0x1f=i,当i>31则进入数组下一个小标。
} void CBitMap::clr(int i) { a[i>>SHIFT] &= ~(1<<(i&MASK)); } bool CBitMap::test(int i) { return a[i>>SHIFT]&(1<<(i&MASK)); }
/---------------------------------------------------------------------------------主程序------------------------------------------------------------------------------------------/
/************************************************************************************************************************************************** * 位向量排序 *1、适用场合:(1)输入数据限制在相对较小的范围内; * (2)数据没有重复; * (3)除了单一整数外,没有任何其他关联数据。 *2、实现功能:将一个给定文件中的0~1000 0000以内的800 0000个随机的互不相等的整数按序输出。 *3、实现步骤:(1)随机生成0~1000 0000以内的800 0000个随机的互不相等的整数,并写入文档中; * (2)位向量的实现;(置位、清零、测试) * (3)读入文档,输出排序后的文档; ***************************************************************************************************************************************************/ #include "stdafx.h" #include "CBitMap.h" #include <fstream> using namespace std; #define N 10000000 int _tmain(int argc, _TCHAR* argv[]) { CBitMap BitMap(N); // 实例化一个位向量(位数为N) ifstream ifs("data.txt"); // 实例化一个输入文件流对象,并与data.txt关联 ofstream ofs("dataSorted.txt"); // 实例化一个输出文件流对象,并与data.txt关联 int i = 0, data = 0; for(i=0; i<N; i++) // 位向量初始化(每位为0) BitMap.clr(i); while(ifs.good()) // 检查文件I/O操作是否异常((badbit, eofbit or failbit) { ifs>>data; // 从文件流对象读取一个数据 BitMap.set(data); // 将位向量中相应的位置1(eg:data=211, 则将第211位置1) } ifs.close(); // 文件读取完毕后关闭文件 for(i=0; i<N; i++) { if(BitMap.test(i)) // 从小到大输出位向量为1的位的位置,即从小到大排列data.txt中的数 ofs<<i<<endl; } ofs.close(); return 0; }
data.txt
267 242
25 153
149 16
227 278
147 73
166 61
229 287
68 113
243 163
216 225
185 186179
19479
34 250
8 140162
217 54
63 156
7 241 95142
264112
83 19 215173
71 284
182 265
274 143
59 236
121 14
76 270
206 187
100 210
167 11
290 191
152 1 102134
150281
96 124
58 223
200 26
172 86
292 282
188 239
271 82
145 131
137 120
75 181
87 154
24 203
256 161
115 109
234 48
174 226
13 2 12629
285 232
28 222
17 158
35 169
51 273
5 66 20798
93 272
70 62 16874
81 6
9 246
253 40
104 53132
94 32
248 133
240
55 238
297 25123
204 171
31
105266
datasorted.txt
1 2
5 6 78
9 11
13 14
16 17 1923
24 25
26 2829
31
32 34 3540
48 51
53 5455
58
59 61 6263
66 68
70 7173
74
75 76 7981
82 83
86 8793
94
95 96 98100
102104
105109
112113
115 120
121 124
126 131
132 133
134 137
140 142
143 145
147 149
150 152
153 154
156 158
161 162
163 166
167 168
169 171
172 173
174 179
181 182
185 186
187 188
191 194
200 203
204 206
207 210
215 216
217 222
223 225
226 227
229 232
234 236
238 239
240 241
242 243
246 248
250 251
253 256
264 265
266 267
270 271
272 273
274 278
281 282
284 285
287 290
292 297
相关文章推荐
- 各种排序(数据结构复习之内部排序算法总结)
- 【排序算法总结】直接插入排序
- 排序算法总结(五)快速排序
- 16 - 12 - 19 十大排序算法总结(四) 之 快速排序
- 排序算法总结之排序概述
- 排序算法总结(六)归并排序
- 排序算法总结(三)选择排序【Select Sort】
- [置顶] 各种常用的排序算法实现对数组的排序——整理总结(代码实现)
- 基本排序(五):基本排序算法的总结
- 排序算法总结---交换排序之快速排序
- Java排序算法以及算法改进总结(计数排序、基数排序、桶排序)
- 排序算法总结---树形选择排序,堆排序
- 排序算法总结之直接插入排序
- 程序猿找工作必练内功:排序算法大总结(五)——线性时间排序算法(计数排序,基数排序,桶排序)
- 排序1+5:各种排序算法的总结和比较
- 常用排序算法总结8一一基数排序
- 排序算法总结---直接插入排序
- 常见的五类排序算法图解和实现(多关键字排序:基数排序以及各个排序算法的总结)
- 排序算法总结之桶排序 Bucket Sort
- 常用排序算法总结2一一选择排序