第一章:开篇

问题描述

对磁盘内的文件进行排序:

  1. 输入:一个文件包括n个整数,每个整数都小于n,n = 10^7.文件内没有重复的数字
  2. 输出:以升序排列的数字序列
  3. 约束:内存最多使用1M,有充足的磁盘空间,运行时间最多为几分钟,最好控制在10秒钟

    对于这个问题,书上给了3种方法:

    1. 使用MergeSort来排序输入文件,但是由于文件中整数过多,还是要花费几天的时间。
    2. 使用QuickSort排序,需要读取输入文件40次,但只输出一次。
    3. 结合上述两种方法的优点

用bitmap的方法,例如集合{1,2,3,5,8,13},我们可以用字符串
0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 来表示,那么10^7个整数就可以用1000万位来表示,只要输入文件中存在那个数字,则就表示为“1”,反之为“0”。所以整个过程可以表示为以下伪代码:

/* 第一个阶段:初始化集合 */
for i = [0,n)
    bit[i] = 0;
/* 第二个阶段:将输入文件的数用位图表示出来 */
for each i in the input file
    bit[i] = 1;
/* 第三个阶段:将排序结果写在输出文件上 */
for i = [0.n)
    if bit[i] == 1
        write i on the output file

习题

  1. 如果空间足够,你将如何使用一种语言来实现排序
//快速排序

int Patition(ElemType A[],int low,int high)
{
    int pivot = A[low];
    while(low < high)
    {
        while(low < high && A[high] >= pivot) high--;
        A[low] = A[high];
        while(low < high && A[low] <= pivot) low++;
        A[high] = A[low];
    }
    A[low] = pivot;
    return low;
}

void QuickSort(ElemType A[],int low,int high)
{
    if(low < high)
    {
        int pivot = Patition(A,low,high);
        QuickSort(A,low,pivot-1);
        QuickSort(A,pivot+1,high);
    }
}

2.如何用二进制逻辑运算符(or,and,shift)来实现位向量呢?

//如何使用位逻辑运算(例如与、或、移位)来实现位向量
/* Copyright (C) 1999 Lucent Technologies */
/* From 'Programming Pearls' by Jon Bentley */

/* bitsort.c -- bitmap sort from Column 1
* Sort distinct integers in the range [0..N-1]
* 排序在0到N-1范围内的无重复整数
*/

#include <stdio.h>

#define BITSTEPWORD 32     //表示一个整型含有32个位
#define SHIFT 5        //单次位移量
#define MASK 0x1F        //掩码
#define NUM 10000000    //表示1000万个整数
int array[1 + NUM / BITSTEPWORD];//使用整型数组模拟定义1000万个位的数组

/*功能:设置位数组中的从0开始的第i位为1
 *参数:需要设置为1的位
 */
void set(int i)
{
    array[i >> SHIFT] |= (1 << (i & MASK));    
}                                           
/* i >> SHIFT 的功能是先选中i所在的int小组,共有1 + NUM / BITSTEPWORD个小组然后(1 << (i & MASK))的功能就是选中小组中的第几位,因为数组从0开始,所以要左移一位,最后 ||就起到了设置“1”的作用
*/
/*
 *功能:设置位数组中的从0开始的第i位为0
 *参数:需要设置为0的位
 */
void clr(int i)
{
    array[i >> SHIFT] &= ~(1 << (i & MASK));
}
 /*
  *功能:取出从0开始的第i位的值,用于检测
  */
void test(int i)
{
    return array[i >> SHIFT] & (1 << (i & MASK));
} 

int main(void)
{
    int i;
    clear();
    for( i = 0; i < 100; i++ )
        set( i*2 );
    for( i = 0; i < 200; i++ )
        printf("%d",test(i) ? 1:0 );
    puts("");
    return 0;
}

3.在系统中实现位图排序,并测试运行时间,且和第一题的快排进行比较。

4.生成[0,n)之间k个不重复的数字

int array[n + 1];
void make_data(int n)
{
    if(n <= 0)
    {
        return;
    }
    for(int i = 0; i < n; i++)
    {
        array[i] = i + 1;
    }

    for(int i = 0; i < n; i++)
    {
        int ii = (rand() * RAND_MAX + rand()) % n;
        int jj = (rand() * RAND_MAX + rand()) % n;
        swap(array[ii], array[jj]);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_19894073/article/details/64469423