编程之美:第四章 数字之趣 4.5磁带文件存放优化

/*
磁带文件存放优化:
磁带是一种线性存储设备,一个文件在磁带上的存储区域是完整而且连续的,而多个文件的存储区域是相互独立且连续分布的。磁带没有山区,柱面,磁道等,
所以再进行文件寻址时需要耗费线性时间,即要定位到磁带上的第n个文件,需要依次经过前面的n-1个文件的磁带长度。磁盘式存储设备一半能以低于线性时间
的效率进行寻址,但他可以进行海量存储。
File1  File2  File3
大型数据中心采用磁带SAN(存储区域网络)作为备份设备。

问题:
假设其中一盘磁带上有n分文件,他们的长度分别为L[0],L[1],...,L[n-1],且被访问的概率分别是P[0],P[1],...,P[n-1]。请问怎么安排他们在磁带上的存储顺序
最好。

本质:
哈弗曼的可变字长编码方式。参见王道论坛:求哈弗曼树的带权长度之和。可以看做单链表

分析:
磁带,对于第n个文件的寻址需要经过前面n-1个文件的磁带长度。因此将最不容易访问的放到后面,将最容易访问的放到前面。

E(L) = i从0到n-1 对(p[i] * [j从0到i L[j]的累加 ])  累加

举例子:
假设连个文件A和B,长度L分别为10,6,被访问的概率分别为0.4,0.6.
如果把B放在前面,则平均访问长度 = 6*0.6 + (10+6)*0.4 = 3.6 + 6.4 = 10,分析概率/访问长度,第一个文件P/L = 0.6/6 = 0.1,第二个文件P/L = 0.4/16=0.025
      A                         =10*0.4 + (10+6)*0.6 = 4 + 9.6 = 13.6                               P/L = 0.4/10= 0.04,         P/L = 0.6/16=0.0375

牛逼啊:
我们只需判断P[i]/L[i]的值按照从大到小排列,即为最佳顺序

输入:
2(文件个数)
10(文件长度) 0.4(文件访问概率)
6 0.6
输出:(按照文件长度,输出其最佳顺序)
10 6
*/

/*
关键:
1 return (_dProbability / _dLen) < (other._dProbability / other._dLen);//注意,分析出来的结果需要按照 概率/长度 从小到大依次的顺序作为最终顺序 
2 分析的结果,如果访问概率相同,那么让最短的文件放在最前面,这样 概率/长度 = 前面大后面小,违背了之前得出的规律
3                 长度相同    ,按访问概率从大到小排好    ,     概率/长度 = 前面大后面小,违背
4 E(L) = i从0到n-1 对(p[i] * [j从0到i L[j]的累加 ])  累加
*/

#include <stdio.h>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXSIZE = 10000;

typedef float ElementType;//type后代前,define前代后

typedef struct Tape
{
	bool operator < (const Tape& other) const 
	{
		return (_dProbability / _dLen) < (other._dProbability / other._dLen);//注意,分析出来的结果需要按照 概率/长度 从小到大依次的顺序作为最终顺序 
	}
	ElementType _dLen;
	ElementType _dProbability;
}Tape;

void print(Tape* tapeArr,int iLen)
{
	for(int i = 0 ; i < iLen ; i++)
	{
		if(i)
		{
			printf(" %.0f",tapeArr[i]._dLen);
		}
		else
		{
			printf("%.0f",tapeArr[i]._dLen);
		}
	}
	printf("\n");
}

void process()
{
	int n;
	Tape tapeArr[MAXSIZE];
	while(EOF != scanf("%d",&n))
	{
		if( n <= 0)
		{
			continue;
		}
		for(int i = 0 ; i < n ; i++)
		{
			scanf("%f %f",&tapeArr[i]._dLen,&tapeArr[i]._dProbability);
		}
		sort(tapeArr,tapeArr+n);
		print(tapeArr,n);
	}
}

int main(int argc,char* argv[])
{
	process();
	getchar();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值