• 文件中随机读取行问题


    1. 有一个文件,如何在不知道有多少行的情况下读取该文件,从中随机选择并输出一行

    当我们读取第 i (i  > 0) 行时,以 1 / i 的概率选择第 i 行,并替换掉原来选的行。
    即总选择第一行,并以概率 1 / 2 选择第 2 行,以概率 1 / 3 选择第 3 行,依次类推。
    到文件结束时,每个行被选中的概率都相等。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #define MAX_LINE_LEN 4096
    int main()
    {
    	srand(time(NULL));
    	const char *filename = "input.txt";
    	FILE * file = fopen(filename, "r");
    	char line_buffer[MAX_LINE_LEN];
    	char selection[MAX_LINE_LEN];
    	int i = 1;
    	while(fgets(line_buffer, MAX_LINE_LEN, file))
    	{
    		if(rand()%i == 0)
    			strcpy(selection, line_buffer);
    		++i;
    	}
    	puts(selection);
    	fclose(file);
    	return 0;
    }
    

    简单推一下。
    到  行时,没问题,跳过。
    到第 2 行时,第 2 行被选中的概率是 1 / 2,那第 1 行被选中的概率也是 1 / 2
    到第 3 行时,第 3 行被选中的概率是 1 / 3,第 1 行和第 2 行被选中的概率是 (1 / 2) * (2 / 3),依次递推。
    到第 i 行时,第  1 ~ i 行每行被选中的概率都是 1 / i ,到文件最后一行也是这样。

    2. 有一个文件,如何在不知道有多少行的情况下读取该文件,从中随机选择并输出k行(假设保证k小于文件总行数)

    先读入第 1 ~ k 行保存,以后每次读入第 i 行,都以 k / i 的概率把刚读入的一行随机替换之前保存的 k 行中的一行。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #define MAX_LINE_LEN 4096
    int main()
    {
    	int k = 5;
    
    	srand(time(NULL));
    
    	char line_buffer[MAX_LINE_LEN];
    	char **selections = (char **)malloc(k*sizeof(char*));
    	for(int i = 0; i < k; ++i)
    		selections[i] = (char *)malloc(MAX_LINE_LEN*sizeof(char));
    
    	const char *filename = "input.txt";
    	FILE * file = fopen(filename, "r");
    
    	// 先读取 1 ~ k 行
    	for(int i = 0; i < k; ++i)
    		fgets(selections[i], MAX_LINE_LEN, file);
    
    	int i = k+1;
    	while(fgets(line_buffer, MAX_LINE_LEN, file))
    	{
    		if(rand()%i < k) 
    		{
    			// 随机替换已有的某一行
    			int j = rand()%k;
    			strcpy(selections[j], line_buffer);
    		}
    		++i;
    	}
    	for(int i = 0; i < k; ++i)
    		puts(selections[i]);
    
    	fclose(file);
    	for(int i = 0; i < k; ++i)
    		free(selections[i]);
    	free(selections);
    
    	return 0;
    }
    

    简单推一下。
    1 ~ i  ( i  >=  k ) 行每行被选中的概率都为 k / i ,当我们读取第 i + 1 行时,以 k / (i+1) 的概率保留该行,并随机替换已保存的某一行(已保存的每行被替换掉的概率是 1 / k )。这样,第 i + 1 行被选取的概率是 k / (i + 1) ,其他行被选取的概率为
    ( k / i ) * (1 - k / ( i + 1 ) )  + ( k / i) * (k / ( i + 1 )) *  ( 1 - 1 / k )
    前面的是第 i + 1 行不被保留时的情况,后面的是第 i+1 行保留并把该行替换掉的情况,最终结果也是 k / ( i + 1 ),所以到第 i + 1 行为止,每行被选取的概率仍然都相同。到文件结尾同样满足。



  • 相关阅读:
    SQL语句获取数据库名、表名、储存过程以及参数列表 狼
    CKEditor3.3+CKFinder2.0附带CKF去除水印 狼
    media player 和realplayer 编程接口 狼
    教您如何去认识人!(识人术) 狼
    引用 JS判断浏览器类型方法 狼
    (转)初始化多维数组
    kmeans 聚类 (代码为: 博客数据聚类) (python )
    对博客订阅源URL中的单词进行计数 (仅限英文博客,中文订阅源不支持 )
    eclipse +python 修改 各种颜色 +字体
    常见错误收集: lucene 读取word文档问题
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3097640.html
Copyright © 2020-2023  润新知