魔兽世界音乐文件的文件可以一个一个拖到硬盘不 ??

热门搜索:
为啥我的魔兽世界大号带小号所有的号都是一个设置啊!! 例如我在那大号上的地图上设置的是采矿上小号还是采矿
小站会根据您的关注,为您发现更多,
看到喜欢的小站就马上关注吧!
下一站,你会遇见谁的梦想?
本站旨在依靠学生团队打造一个较为专业的软件视频培训、交流、合作平台,结识更多的软件爱好者,揭开软件神秘面纱,一起为未来加油!&&PS:如果你觉得本站不错,请猛击右上角星星“推荐”哦!谢谢!!&&&==============================================================================&&&&&&/*&&微信“求职是落点”,人人公众平台“中哥教面试”欢迎关注!*/&&==============================================================================&
C++最反直觉的地方
会自动把&引用&去除掉
,而不是对象&&的类型是,而不是时,要特别注意别多加了括号。或,而不是所希望的或!、右值引用只是简单的将类型转成右值引用而已!!!&可以理解成&或&。的类型是,而不是的类型是!&必须转换类型的类型是,而不是。的类型是的话,就会有副作用:值,但实际上值不会改变,改变的是临时对像,函数可以修改临时对像,,感觉后者更容易理解。类型为&、&,经过类型转换后,其类型还是和原来的一样。中(在中,这种写法是非法的)
&&&来自##61##小狼
如何做出优秀的应用?
Instagram创始人Krieger的答案是,仔细观察人们在生活中真正需要什么,而不是瞎猜。他在500&Startup举办的集会上分享了他在产品设计上的八点体会。
开篇就表示:&在Google上搜索过某个东西不代表你真的了解这个东西,&要想真正创建某个产品来解决问题,&你得比人们更了解他们自己。&
比如说你希望颠覆现在的购物体验,你就得真正明白现在的购物体验和行为模式到底是怎样的。&去大卖场或者精品店站3个小时,好好观察人们是怎么购物的,&这就是Krieger的建议。认真观察之后,你得有自己独到的洞见,而不只是一些既定现实。Krieger称他最喜欢的&洞见&定义就是:那些让你激动不已、希望跟地铁上的陌生人分享的东西。
1.&从旧有的经验出发:创业公司很忌讳处在&寻找问题&的阶段,不要去凭空设想一个问题,想想过去你曾经思考过的,在这些领域你有更多的了解。
2.&知道自己有什么不同之处:明白自己的创业公司跟别人有什么不同,弄清为什么现在是一个特殊的机会。
3.&先画草图再写代码:Instagram的另一名创始人Systrom经常会拿着iPhone设计纸板,去咖啡厅坐着,然后一起商量哪些功能要保留哪些要删掉。也许你会浪费掉几张设计纸板,但是不会浪费几周时间去写代码。
4.&每周进步一点:我们一直在问自己这些问题,&用户会喜欢移动分享图片吗?我们可以做出一些看起来不错的滤镜吗?&花上一周时间调查,周五有了结论之后下周继续。
5.&在日常生活场景中验证功能:Krieger称之为&酒吧检测&,将某个功能解释给酒吧里的一个陌生人听,如果对方听不懂,那就表明需要简化。不要只是找你周围的技术帝朋友测试新功能。&
6.&知道何时应该转型:虽然现在Pivot(转型)已经不是什么好词了,但是当你发现已经没有什么问题可以解决了,那就是该转型的时候到了。
7.&社会化原型测试:没必要一开始就写出所有的代码,你可以隐藏在幕后做人工测试。Instagram的早期版本中曾考虑加入这样的一个功能:当你的朋友加入时给你提醒。Krieger没有直接把这个功能做出来然后测试,而是用人工方式手动给用户发送通知,结果用户的反馈不理想,于是这个功能就没有做了。&我们一行代码都没写,所以一行代码也不用删了。&
8.&同你的用户保持顺畅的沟通:不要用几个月时间埋头做产品,却不知道这个功能到底是不是用户需要的。
&&来自##66##毅
一定要知道的Web设计八个流行趋势
& & & &必须得大大方方。要是公司网页代表不了自身形象,千万不能怪客户的肤浅和先入为主,怪就得怪自家网站的设计太落伍和守旧。
设计是怎样的吗为此,我们从过去几年目睹的网站中总结分析出了一些当下网页流行的设计元素。当然,这个并非是什么终极榜单但是,我们预测,在往后的日子,里面提及到的设计流行趋势依然会大行其道。
荐和注重字体排印等八大趋势。
:单页网站
单页网站的就应运而生了。一些相当有名和成功的公司包括公司都用了长长的页面来介绍其产品,而且还大获成功。
单页网站设计的时候,一屏与另一屏之间,最好用颜色相近和谐但又能区分界线的不同背景轮换。
:用图片做背景
:实心砌块
:超大号图像
图标的流行起来有关。程序员要在的应用中推广网站,通常得将自身的品牌设计成超大号的样式。久而久之,的程序开发人员都采用了这种超大号图像的方式。因而,它也渐渐在现代设计文化占据一席之位了。
:越简单越好
年的设计流行趋势之巅很多网站都更加注重简洁直观的设计。极简主义的设计,通过整合或者删除不必要的页面,能够将用户所需的信息更加有效地呈递给他们。通常可以用以下的手法到达突出重点的目的:运用大号字体、粗体字体,以及超大号图像等等。
:响应式网页设计
响应式网页设计这一趋势了。
:视差滚动成动
是在当两个或多个相互平行的物体以不同的速度移动的时候形成的。
视差滚动:当滚动鼠标的时候,页面上的不同物体,会根据鼠标的滚动以不同速度发生运动,从而在视觉上形成动感的效果。如果还不好理解,请点击如下的网站,并滚动鼠标进行体验。体验时,建议使用浏览器。
视差的功能,该趋势可能会大幅抢占市场,打破以往网页内容线性单一的模式。现时,已经有不少美轮美奂的网站应用视觉滚动技术了。
:注重字体排印
和的网页字体库为设计人员提供了几乎数不过来的字体样式。有了它们,设计人员就可以随心所欲地施展拳脚,将网页设计得更加吸引人。
但是通过匠心独运地布局多种多样的字体来美化网页,已经形成了设计热门方向。诸如那样的网站,它们几乎仅仅通过字体就将网站设计得令人赏心悦目了。
设计流行趋势,相信这些趋势在未来几年都不会显得过时的,希望读者自己能够从中择而用之吧。
史上性价比最低的15大电子产品
作者:eoe移动开发门户 来源: &导读:一些科技公司高估了他们产品的实力,又低估了消费者的智商,结果就是很多电子产品的价格并不符合他们在市 场上的真正价值。  近日国外知名媒体评出了15大定价过高的电子产品。事实上,电子产品要价过高并没什么错,因为生命中最好的往往都不是免费的,一 个真正卓越的产品是值得你多花点钱的。不幸的是,一些科技公司高估了他们产品的实力,又低估了消费者的智商,结果就是很多电子产品的价格并不符合他们在市 场上的真正价值。  搭载Windows RT的微软Surface,要价629美元。
  你认为一款配有新型移动屋盖的新产品,价格定在2.2万美元如何?这里有一个陷阱,你必须为你经常在商业广告中看到的该移动屋盖多付1万美元。  微 软的首部平板电脑基价为499美元,该产品的成本和已在市场上站稳脚跟的iPad 4相同。但相比起来,这款引人注目的Surface也有不少缺点,屏幕 显示效果逊于iPad,一次充电的续航时间只有不到5小时,且发布时只有为数不多的应用程序能运行在Windows RT操作系统上。  尽管 有上述种种缺点,你可能仍然想要一个Surface,因为微软一直在加大力度宣传该款产品配置的Touch Cover键盘,而这一必备产品又会花费你 119美元,尽管其成本价只有16美元。总之,你需要花费629美元才能购得这款平板电脑,但其性能和价格为499美元的iPad在很多方面还相差很多。  惠普的Voodoo Envy 133笔记本,要价2099美元至3299美元
  2008年最备受期待的产品是惠普7英寸的超薄Envy 133笔记本,想必你和你的朋友都知道该款产品。Envy 133的最初定价为2099美元,之后其完整组装版又上涨到3300美元。但该款3.4磅的笔记本如此高昂的价格与其略逊的性能与规格不太相符。  这 款高端的Envy 133笔记本搭载主频为1.8GHz的英特尔酷睿2双核处理器,2GB的RAM和64GB的内部闪存。这些配置很一般,即使是在复制文 件时速度都很慢。与其说它是个固态硬盘还不如说它是个&固态公园&。更糟糕的是,该款笔记本一次充电的续航时间只有2小时32分钟,号称是&超级便携&的 Envy 133笔记本电脑其实也并不那么便携。  思科的Umi, 要价599美元,用户每月还需再支付24.99美元
  &&喂,到我这儿来。我有一份本周的《村声》报纸,我可以以25美元的价格卖给你。&  &&什么?这是免费的,你不知道吗?&  &&我知道,但我的版本印刷更清晰,我确信你和其他人肯定会购买我的版本的。&  思 科在2010年推出Umi家庭视频会议系统时就套用了上述对话的逻辑。该款产品要价高的离谱,599美元,用户还需每个月再交付24.99美元。但Umi 只比Skype和Google Talk好用那么一点点而后两者的服务是完全免费的。有了Umi,人和人之间的距离就能缩短,你还能在电视机顶部安装一个 摄像头,和你的另外5位Umi用户聊天。当然,你也可以和你的朋友在谷歌上视频聊天,而该方法却不会花费你一分钱。  索尼的VAIO P系列上网本,要价899美元
  回到2009年,当上网本还不像歌手组合乔纳斯兄弟那样炙手可热时,每个公司都希望能尽快加入到此领域中。在底端领域,西尔瓦尼亚(Sylvania)等非电脑公司都在制作自己的上网本。而在高端领域,索尼尝试重新推出重1.4磅、屏幕8英寸的VAIO P系列上网本。  乍 看之下,该系列确实是一次工程奇迹。轻薄的特点使其能够轻松地放入大衣口袋里,还有一些高级功能,如1600 x 768的高像素显示屏和3G连接功能。 但是该系列上网本的性能却广为人诟病,电池续航时间一般,键盘也不好用,另外,该系列上网本的配置也不足以用作其它用途。当市场上有性能更好的上网本,且 价格只为499美元时,899美元的价格很显然和该系列价值不符。  苹果的Lisa个人电脑,要价1万美元
  在20世纪80年代早期,很少有人见过一台配有图形用户界面的电脑。Xerox公司自70年代以来一直在研发图形用户界面的电脑,并在1981年推出了其Xerox Star 8010。但在1983年苹果推出的Lisa个人电脑却最终将窗口式的操作系统带入了主流市场。  不 幸的是,想要在Lisa12英寸、分辨率720x360的黑白屏幕上滚动鼠标,你还需要再付1万美元(以2011年的物价计算,即2.2万美元),你还要 忍受一对不太可靠的Twiggy软盘驱动器。但同时,你也可以以1395美元购买最新的Apple IIe,一款主流的家用电脑,或是3590美元购买康 伯Portable PC便携式电脑,或是以更低的价格买一款早期的电脑。  诺基亚的Booklet 3G,要价1720美元
  推出有两年期限3G合同的补贴上网本永远都不是什么好主意,这对于诺基亚在2010 年推出的Booklet 3G再适用不过了。 消费者需要首先交付299美元购得设备,之后两年内的还需每月再给AT&T交付60美元(一共 1720美元),才能获得这款诱人但显然没什么用的10英寸的上网本。  也许诺基亚和AT&T认为Booklet的Macbook式的铝制底盘会分散消费者的注意,使他们意识不到该产品4200-rpm的硬盘会降低Atom Z530处理器的运行速度。  播放器DivX,要价499美元,每个电影硬盘要价4.5美元
  你愿意花500美元买一个播放器,然后每次在你想要租电影看的时候再花4.5美元吗?这就是DivX背后的盈利模式。该款播放器在20世纪90年代后期推出。想必设计师肯定是看过不少《碟中谍》才设计出该款自毁前程的播放媒体。  在 花了500美元购得一部DivX播放器后,你还需要再花费4.5美元购买一个包含任意400部电影的硬盘。在你看这些电影48小时之后,你很可能会想要扔 掉这张硬盘或是再花3.25美元另买一张硬盘。消费类电子零售商Circuit City是销售DivX播放器和硬盘的佼佼者,该公司吹捧这种新技术能方 便人们的生活且不用再交付后期的费用。但是,该播放器相比于其他普通的DVD来说贵了100美元,而且这种硬盘的价格比在商店里租光碟要贵得多。  黑莓的Playbook,要价499美元
  RIM(Research In Motion)的两位CEO麦克&拉扎里迪斯 (Mike Lazaridis)和吉姆&巴尔斯利(Jim Balsillie)在为公司2011年春季推出的第一部平板电脑定价时肯定吃了一些影响精 神的黑莓。该款平板电脑价格定位在499美元,和iPad 2的定价一样。但黑莓平板Playbook的屏幕狭小,操作系统也不成熟甚至在发布时连收发邮 件的功能都没有。  在Playbook推出的几个月后,价格就直线下降。今天,你能以180美元的价格购得一部Playbook,但这个价格 还是太贵。一些更好的设备,如配有7英寸大小的安卓设备Nexus 7和亚马逊的Kindle Fire的价格也为180美元,但却拥有更好的应用配置。  摩托罗拉的笔记本电脑Dock,要价499美元
  一款双核的智能手机如今比一款陈旧的PC功能更强大,所以为什么不用智能手机作电脑使 呢?这就是摩托罗拉设计笔记本电脑Laptop Dock的背后初衷。该款笔记本键盘和屏幕结合,Atrix 4G智能手机俨然变成了一款笔记本,并搭载 了以浏览方式为中心的Webtop操作系统该款产品定价为499美元,如果消费者两者一起购买,价格就为300美元。这款配有11.6英寸的 Laptop Dock和已在市场上成熟的Windows 7上网本价格一样,而后者能够运行所有电脑的软件。该款产品的键盘和其他的上网本相比也较为难 用。摩托罗拉是2011年索价最高的几款产品之一。  AT&T的 VideoPhone 2500, 要价1599美元
  今天,任何人都可以使用 Skype,Google Talk,FaceTime或是其他方法免费的在网上视频聊天。但在1992年时,我们还没有宽带互联网或是高清的网络摄像 头。所以当AT&T推出了一款标准的固定电话VideoPhone 2500时,该设备视频通话的功能还是获得了一些关注,但真正让世界震惊的是 它的价格,1599美元。  VideoPhone能够让人在速度极慢的19.2bpbs调制解调器上视频聊天,该产品的每秒10帧的运行速度更是让人&佩服不已&。但是,要使用该设备,你需要你的朋友们和亲戚们都买一部VideoPhone,而大部分的消费者都不愿意购买。  苹果的Macintosh G4 Cube,要价1799美元
  想要变得性感,你愿意多掏多少钱?在2000年,如果你是一个Mac粉 的话,乔布斯认为你会愿意再掏1799美元购得一部Macintosh G4 Cube。这是苹果PowerMac G4台式电脑的小正方形版。不幸的 是,如此高的价格使Cube并不适合进入苹果的生产线。  当时,消费者愿意花1000美元买一台包含处理器的iMac。而富有创造力专业人员们更愿意买一台性能更好并且具备升级能力的 PowerMac G4 tower。  摩托罗拉的Xoom,要价1079美元
  在2011年早期谷歌和摩托罗拉发布了第一部真正意义上的平板电脑。其实早在一年前,平板电脑 市场就在不断发展壮大,这两家公司算是姗姗来迟,但他们想要的却更多。当时,Wi-Fi版的iPad 2定价为499美元,不受合同限制的3G版iPad 定价699美元,而摩托罗拉的Xoom竟然要价599美元,并且还要求消费者和Verizon签订为期两年的协议,每个月用户至少需要交付20美元(一共 为1079美元)或是无合同的799美元。更为便宜的iPad 2有上千个应用供用户选择,而Xoom只有少得可怜的46款应用。  IBM的PC Jr,要价699美元或是1269美元
  1983年IBM推出的PC Jr和前一代基本上同出一辙,可以说该款产品要价 过高。消费者需支付1269美元才能得到一款带有必要的软盘驱动器的电脑,或者支付669美元购得一部无软盘驱动器的电脑。PC Jr只比当时IBM非常 成熟的个人电脑便宜一点,却比家庭电脑产品,如价格为200美元的 Commodore 64和价格为150美元的TI-99/4A贵了许多。  不幸的是,该款电脑的键盘难以使用,性能糟糕,众多兼容性问题导致其不能运行一些常见的电脑程序。显然,PC Jr并不值那么多钱。  OQO的Model 01,要价1899美元
  OQO在2004年推出了世界上第一部重14盎司的Windows个人电脑。该款设备 Model 01其实是个真正的开拓者,但以21世纪早期的标准,该款小型设备搭载的1GHz的全美达CPU,20G的硬盘以及256MB的RAM,其性 能糟糕也就不足为怪。同时,如此小的键盘也让人觉得不舒服。  你可以以更低的价格购得一款性能更为良好的电脑。对于大部分的消费者和商业用户来说,他们绝对不会以如此高的价格购买这部严重被阉割的新品。  苹果的Newton MessagePad 2100,要价1000美元&
  到1997年,苹果提升了其软件性能并解决了很多在其Newton PDA手写识别的问题。很可能是因为这些进步,苹果公司认为对其灰度手持式显示设备可以要价高一些,最终该设备定价为1000美元,比一些PC的价格还要高。  与此同时,掌上电脑PalmPilot Personal的价格仅为299美元。没错,Newton的处理器性能更高,内存更多,屏幕更大,但即使是在网络泡沫期间这些优点也不足以让消费者多花700美元。  &&来自##28##光伟&
由谈谈网站性能技术(转之酷壳网站)
&网站挂了,被全国人民骂了。我这两天也在思考这个事,我想以这个事来粗略地和大家讨论一下网站性能的问题。因为仓促,而且完全基于本人有限的经验和了解,所以,如果有什么问题还请大家一起讨论和指正。(这又是一篇长文,只讨论性能问题,不讨论那些UI,用户体验,或是是否把支付和购票下单环节分开的功能性的东西)业务任何技术都离不开业务需求,所以,要说明性能问题,首先还是想先说说业务问题。其一,有人可能把这个东西和QQ或是网游相比。但我觉得这两者是不一样的,网游和QQ在线或是登录时访问的更多的是用户自己的数据,而订票系统访问的是中心的票量数据,这是不一样的。不要觉得网游或是QQ能行你就以为这是一样的。网游和QQ 的后端负载相对于电子商务的系统还是简单。&其二,有人说春节期间订火车的这个事好像网站的秒杀活动。的确很相似,但是如果你的思考不在表面的话,你会发现这也有些不一样。火车票这个事,还有很多查询操作,查时间,查座位,查铺位,一个车次不 行,又查另一个车次,其伴随着大量的查询操作,下单的时候需要对数据库操作。而秒杀,直接杀就好了。另外,关于秒杀,完全可以做成只接受前N个用户的请求(完全不操作后端的任何数据, 仅仅只是对用户的下单操作log),这种业务,只需要在内存cache中放好可秒杀的数量,还可以把数据分布开来放,100商品,10台服务器一台放10个,无需在当时操作任何数据库。可以订单数够后,停止秒杀,然后批量写数据库。而且秒杀的商品不多。火车票这个不是像秒杀那么简单的,春运时间,几乎所有的票都是热门票,而且几乎是全国人民都来了。(淘宝的双十一也就3百万用户,而火车票瞬时有千万级别甚至是亿级别的)&其三,有人拿这个系统和奥运会的票务系统比较。我觉得还是不一样。虽然奥运会的票务系统当年也一上线就废了。但是奥运会用的是抽奖的方式,也就是说不存在先来先得的抢的方式,而且,是事后抽奖,事前只需要收信息,事前不需要保证数据一致性,没有锁,很容易水平扩展。&其四,订票系统应该和电子商务的订单系统很相似,都是需要对库存进行:1)占住库存,2)支付(可选),3)扣除库存的操作。这个是需要有一致性的检查的,也就是在并发时需要对数据加锁的。B2C的电商基本上都会把这个事干成异步的,也就是说,你下的订单并不是马上处理的,而是延时处理的,只有成功处理了,系统才会给你一封确认邮件说是订单成功。我相信有很多朋友都收到认单不成功的邮件。这就是说,数据一致性在并发下是一个瓶颈。&其五,铁路的票务业务很变态,其采用的是突然放票,而有的票又远远不够大家分,所以,大家才会有抢票这种有中国特色的业务的做法。于是当票放出来的时候,就会有几百万人甚至上千万人杀上去,查询,下单。几十分钟内,一个网站能接受几千万的访问量,这个是很恐怖的事情。据说12306的高峰访问是10亿PV,集中在早8点到10点,每秒PV在高峰时上千万。&多说几句:库存是B2C的恶梦,库存管理相当的复杂。不信,你可以问问所有传统和电务零售业的企业,看看他们管理库存是多么难的一件事。不然,就不会有那么多人在问凡客的库存问题了。(你还可以看看《乔布斯传》,你就知道为什么Tim会接任Apple的CEO了,最主要的原因是他搞定了苹果的库存周期问题)&对于一个网站来说,浏览网页的高负载很容易搞定,查询的负载有一定的难度去处理,不过还是可以通过缓存查询结果来搞定,最难的就是下单的负载。因为要访问库存啊,对于下单,基本上是用异步来搞定的。去年双11节,淘宝的每小时的订单数大约在60万左右,京东一天也才能支持40万(居然比12306还差),亚马逊5年前一小时可支持70万订单量。可见,下订单的操作并没有我们相像的那么性能高。&淘宝要比B2C的网站要简单得多,因为没有仓库,所以,不存在像B2C这样有N个仓库对同一商品库存更新和查询的操作。下单的时候,B2C的 网站要去找一个仓库,又要离用户近,又要有库存,这需要很多计算。试想,你在北京买了一本书,北京的仓库没货了,就要从周边的仓库调,那就要去看看沈阳或 是西安的仓库有没有货,如果没有,又得看看江苏的仓库,等等。淘宝的就没有那么多事了,每个商户有自己的库存,库存就是一个数字,并且库存分到商户头上了,反而有利于性能扩展。&数据一致性才是真正的性能瓶颈。有 人说nginx可以搞定每秒10万的静态请求,我不怀疑。但这只是静态请求,理论值,只要带宽、I/O够强,服务器计算能力够,并支持的并发连接数顶得住10万TCP链接的建立 的话,那没有问题。但在数据一致性面前,这10万就完完全全成了一个可望不可及的理论值了。&我说那么多,我只是想从业务上告诉大家,我们需要从业务上真正了解春运铁路订票这样业务的变态之处。前端性能优化技术要解决性能的问题,有很多种常用的方法,我在下面列举一下,我相信12306这个网站使用下面的这些技术会让其性能有质的飞跃。一、前端负载均衡通过DNS的负载均衡器(一般在路由器上根据路由的负载重定向)可以把用户的访问均匀地分散在多个Web服务器上。这样可以减少Web服务器的请求负载。因为http的请求都是短作业,所以,可以通过很简单的负载均衡器来完成这一功能。最好是有CDN网络让用户连接与其最近的服务器(CDN通常伴随着分布式存储)。(关于负载均衡更为详细的说明见&后端的负载均衡&)二、减少前端链接数我看了一下,打开主页需要建60多个HTTP连接,车票预订页面则有70多个HTTP请求,现在的浏览器都是并发请求的(当然,浏览器的一个页面的并发数是有限的,但是你挡不住用户开多个页面,而且,后端服务器TCP链接在前端断开始,还不会马上释放或重要)。所以,只要有100万个用户,就有可能会有6000万个链接(访问第一次后有了浏览器端的cache,这个数会下来,就算只有20%也是百万级的链接数),太多了。一个登录查询页面就好了。把js打成一个文件,把css也打成一个文件,把图标也打成一个文件,用css分块展示。把链接数减到最低。三、减少网页大小增加带宽这个世界不是哪个公司都敢做图片服务的,因为图片太耗带宽了。现在宽带时代很难有人能体会到当拨号时代做个图页都不敢用图片的情形(现在在手机端浏览也是这个情形)。我查看了一下12306首页的需要下载的总文件大小大约在900KB左右,如果你访问过了,浏览器会帮你缓存很多,只需下载10K左右的文件。但是我们可以想像一个极端一点的案例,1百万用户同时访问,且都是第一次访问,每人下载量需要1M,如果需要在120秒内返回,那么就需要,1M * 1M /120 * 8 = 66Gbps的带宽。很惊人吧。所以,我估计在当天,12306的阻塞基本上应该是网络带宽,所以,你可能看到的是没有响应。后面随着浏览器的缓存帮助12306减少很多带宽占用,于是负载一下就到了后端,后端的数据处理瓶颈一下就出来。于是你会看到很多http 500之类的错误。这说明后端服务器垮了。四、前端页面静态化静态化一些不常变的页面和数据,并gzip一下。。使用nginx的sendfile功能可以让这些静态文件直接在内核心态交换,可以极大增加性能。五、优化查询很多人查询都是在查一样的,完全可以用反向代理合并这些并发的相同的查询。这样的技术主要用查询结果缓存来实现,第一次查询走数据库获得数据,并把数据放到缓存,后面的查询统统直接访问高速缓存。为每个查询做Hash,使用NoSQL的技术可以完成这个优化。(这个技术也可以用做静态页面)对于火车票量的查询,个人觉得不要显示数字,就显示一个&有&或&无&就好了,这样可以大大简化系统复杂度,并提升性能。把查询对数据库的负载分出去,从而让数据库可以更好地为下单的人服务。六、缓存的问题缓存可以用来缓存动态页面,也可以用来缓存查询的数据。缓存通常有那么几个问题:1)缓存的更新。也叫缓存和数据库的同步。有这么几种方法,一是缓存time out,让缓存失效,重查,二是,由后端通知更新,一量后端发生变化,通知前端更新。前者实现起来比较简单,但实时性不高,后者实现起来比较复杂 ,但实时性高。2)缓存的换页。内存可能不够,所以,需要把一些不活跃的数据换出内存,这个和操作系统的内存换页和交换内存很相似。FIFO、LRU、LFU都是比较经典的换页算法。相关内容参看Wikipeida的缓存算法。3)缓存的重建和持久化。缓存在内存,系统总要维护,所以,缓存就会丢失,如果缓存没了,就需要重建,如果数据量很大,缓存重建的过程会很慢,这会影响生产环境,所以,缓存的持久化也是需要考虑的。诸多强大的NoSQL都很好支持了上述三大缓存的问题。后端性能优化技术前面讨论了前端性能的优化技术,于是前端可能就不是瓶颈问题了。那么性能问题就会到后端数据上来了。下面说几个后端常见的性能优化技术。一、数据冗余关于数据冗余,也就是说,把我们的数据库的数据冗余处理,也就是减少表连接这样的开销比较大的操作,但这样会牺牲数据的一致性。风险比较大。很多人把NoSQL用做数据,快是快了,因为数据冗余了,但这对数据一致性有大的风险。这需要根据不同的业务进行分析和处理。(注意:用关系型数据库很容易移植到NoSQL上,但是反过来从NoSQL到关系型就难了)二、数据镜像几乎所有主流的数据库都支持镜像,也就是replication。数据库的镜像带来的好处就是可以做负载均衡。把一台数据库的负载均分到多台上,同时又保证了数据一致性(Oracle的SCN)。最重要的是,这样还可以有高可用性,一台废了,还有另一台在服务。数据镜像的数据一致性可能是个复杂的问题,所以我们要在单条数据上进行数据分区,也就是说,把一个畅销商品的库存均分到不同的服务器上,如,一个畅销商品有1万的库存,我们可以设置10台服务器,每台服务器上有1000个库存,这就好像B2C的仓库一样。三、数据分区数据镜像不能解决的一个问题就是数据表里的记录太多,导致数据库操作太慢。所以,把数据分区。数据分区有很多种做法,一般来说有下面这几种:1)把数据把某种逻辑来分类。比如火车票的订票系统可以按各铁路局来分,可按各种车型分,可以按始发站分,可以按目的地分&&,反正就是把一张表拆成多张有一样的字段但是不同种类的表,这样,这些表就可以存在不同的机器上以达到分担负载的目的。2)把数据按字段分,也就是竖着分表。比如把一些不经常改的数据放在一个表里,经常改的数据放在另外多个表里。把一张表变成1对1的关系,这样,你可以减少表的字段个数,同样可以提升一定的性能。另外,字段多会造成一条记录的存储会被放到不同的页表里,这对于读写性能都有问题。但这样一来会有很多复杂的控制。3)平均分表。因为第一种方法是并不一定平均分均,可能某个种类的数据还是很多。所以,也有采用平均分配的方式,通过主键ID的范围来分表。4)同一数据分区。这个在上面数据镜像提过。也就是把同一商品的库存值分到不同的服务器上,比如有10000个库存,可以分到10台服务器上,一台上有1000个库存。然后负载均衡。这三种分区都有好有坏。最常用的还是第一种。数据一旦分区,你就需要有一个或是多个调度来让你的前端程序知道去哪里找数据。把火车票的数据分区,并放在各个省市,会对12306这个系统有非常有意义的质的性能的提高。四、后端系统负载均衡前面说了数据分区,数据分区可以在一定程度上减轻负载,但是无法减轻热销商品的负载,对于火车票来说,可以认为是大城市的某些主干线上的车票。这就需要使用数据镜像来减轻负载。使用数据镜像,你必然要使用负载均衡,在后端,我们可能很难使用像路由器上的负载均衡器,因为那是均衡流量的,因为流量并不代表服务器的繁忙程度。因此,我们需要一个任务分配系统,其还能监控各个服务器的负载情况。任务分配服务器有一些难点:负载情况比较复杂。什么叫忙?是CPU高?还是磁盘I/O高?还是内存使用高?还是并发高?还是内存换页率高?你可能需要全部都要考虑。这些信息要发送给那个任务分配器上,由任务分配器挑选一台负载最轻的服务器来处理。&任务分配服务器上需要对任务队列,不能丢任务啊,所以还需要持久化。并且可以以批量的方式把任务分配给计算服务器。&任务分配服务器死了怎么办?这里需要一些如Live-Standby或是failover等高可用性的技术。我们还需要注意那些持久化了的任务的队列如何转移到别的服务器上的问题。&我看到有很多系统都用静态的方式来分配,有的用hash,有的就简单地轮流分析。这些都不够好,一个是不能完美地负载均衡,另一个静态的方法的致命缺陷是,如果有一台计算服务器死机了,或是我们需要加入新的服务器,对于我们的分配器来说,都需要知道的。另外,还要重算哈希(一致性hash可以部分解决这个问题)。还有一种方法是使用抢占式的方式进行负载均衡,由下游的计算服务器去任务服务器上拿任务。让这些计算服务器自己决定自己是否要任务。这样的好处是可以简化系统的复杂度,而且还可以任意实时地减少或增加计算服务器。但是唯一不好的就是,如果有一些任务只能在某种服务器上处理,这可能会引入一些复杂度。不过总体来说,这种方法可能是比较好的负载均衡。五、异步、 throttle 和 批量处理异步、throttle(节流阀) 和批量处理都需要对并发请求数做队列处理的。异步在业务上一般来说就是收集请求,然后延时处理。在技术上就是可以把各个处理程序做成并行的,也就可以水平扩展了。但是异步的技术问题大概有这些,a)被调用方的结果返回,会涉及进程线程间通信的问题。b)如果程序需要回滚,回滚会有点复杂。c)异步通常都会伴随多线程多进程,并发的控制也相对麻烦一些。d)很多异步系统都用消息机制,消息的丢失和乱序也会是比较复杂的问题。&throttle 技术其实并不提升性能,这个技术主要是防止系统被超过自己不能处理的流量给搞垮了,这其实是个保护机制。使用throttle技术一般来说是对于一些自己无法控制的系统,比如,和你网站对接的银行系统。&批量处理的技术,是把一堆基本相同的请求批量处理。比如,大家同时购买同一个商品,没有必要你买一个我就写一次数据库,完全可以收集到一定数量的请求,一次操作。这个技术可以用作很多方面。比如节省网络带宽,我们都知道网络上的MTU(最大传输单元),以态网是1500字节,光纤可以达到4000多个字节,如果你的一个网络包没有放满这个MTU,那就是在浪费网络带宽,因为网卡的驱动程序只有一块一块地读效率才会高。因此,网络发包时,我们需要收集到足够多的信息后再做网络I/O,这也是一种批量处理的方式。批量处理的敌人是流量低,所以,批量处理的系统一般都会设置上两个阀值,一个是作业量,另一个是timeout,只要有一个条件满足,就会开始提交处理。&所以,只要是异步,一般都会有throttle机制,一般都会有队列来排队,有队列,就会有持久化,而系统一般都会使用批量的方式来处理。云风同学设计的&排队系统& 就是这个技术。这和电子商务的订单系统很相似,就是说,我的系统收到了你的购票下单请求,但是我还没有真正处理,我的系统会跟据我自己的处理能力来throttle住这些大量的请求,并一点一点地处理。一旦处理完成,我就可以发邮件或短信告诉用户你来可以真正购票了。在这里,我想通过业务和用户需求方面讨论一下云风同学的这个排队系统,因为其从技术上看似解决了这个问题,但是从业务和用户需求上来说可能还是有一些值得我们去深入思考的地方:1)队列的DoS攻击。首先,我们思考一下,这个队是个单纯地排队的吗?这样做还不够好,因为这样我们不能杜绝黄牛,而且单纯的ticket_id很容易发生DoS攻击,比如,我发起N个 ticket_id,进入购票流程后,我不买,我就耗你半个小时,很容易我就可以让想买票的人几天都买不到票。有人说,用户应该要用身份证来排队, 这样在购买里就必需要用这个身份证来买,但这也还不能杜绝黄牛排队或是号贩子。因为他们可以注册N个帐号来排队,但就是不买。黄牛这些人这个时候只需要干一个事,把网站搞得正常人不能访问,让用户只能通过他们来买。2)对列的一致性?对这个队列的操作是不是需要锁?只要有锁,性能一定上不去。试想,100万个人同时要求你来分配位置号,这个队列将会成为性能瓶颈。你一定没有数据库实现得性能好,所以,可能比现在还差。抢数据库和抢队列本质上是一样的。3)队列的等待时间。购票时间半小时够不够?多不多?要是那时用户正好不能上网呢?如果时间短了,用户不够时间操作也会抱怨,如果时间长了,后面在排队的那些人也会抱怨。这个方法可能在实际操作上会有很多问题。另外,半个小时太长了,这完全不现实,我们用15分钟来举例:有1千万用户,每一个时刻只能放进去1万个,这1万个用户需要15分钟完成所有操作,那么,这1千万用户全部处理完,需要1000*15m = 250小时,10天半,火车早开了。(我并非信口开河,根据铁道部专家的说明:这几天,平均一天下单100万,所以,处理1000万的用户需要十天。这个计算可能有点简单了,我只是想说,在这样低负载的系统下用排队可能都不能解决业务问题)4)队列的分布式。这个排队系统只有一个队列好吗?还不足够好。因为,如果你放进去的可以购票的人如果在买同一个车次的同样的类型的票(比如某动车卧铺),还是等于在抢票,也就是说系统的负载还是会有可能集中到其中某台服务器上。因此,最好的方法是根据用户的需求&&提供出发地和目的地,来对用户进行排队。而这样一来,队列也就可以是多个,只要是多个队列,就可以水平扩展了。这样可以解决性能问题,但是没有解决用户长时间排队的问题。我觉得完全可以向网上购物学习。在排队(下单)的时候,收集好用户的信息和想要买的票,并允许用户设置购票的优先级,比如,A车次卧铺买 不到就买 B车次的卧铺,如果还买不到就买硬座等等,然后用户把所需的钱先充值好,接下来就是系统完全自动地异步处理订单。成功不成功都发短信或邮件通知用户。这样,系统不仅可以省去那半个小时的用户交互时间,自动化加快处理,还可以合并相同购票请求的人,进行批处理(减少数据库的操作次数)。这种方法最妙的事是可以知道这些排队用户的需求,不但可以优化用户的队列,把用户分布到不同的队列,还可以像亚马逊的心愿单一样,通过一些计算就可以让铁道部做车次统筹安排和调整(最后,排队系统(下单系统)还是要保存在数据库里的或做持久化,不能只放在内存中,不然机器一down,就等着被骂吧)。小结写了那么多,我小结一下:0)无论你怎么设计,你的系统一定要能容易地水平扩展。也就是说,你的整个数据流中,所有的环节都要能够水平扩展。这样,当你的系统有性能问题时,&加30倍的服务器&才不会被人讥笑。1)上述的技术不是一朝一夕能搞定的,没有长期的积累,基本无望。我们可以看到,无论你用哪种都会引发一些复杂性,设计总是在做一种权衡。2)集中式的卖票很难搞定,使用上述的技术可以让订票系统能有几佰倍的性能提升。而在各个省市建分站,分开卖票,是能让现有系统性能有质的提升的最好方法。3)春运前夕抢票且票量供远小于求这种业务模式是相当变态的,让几千万甚至上亿的人在某个早晨的8点钟同时登录同时抢票的这种业务模式是变态中的变态。业务形态的变态决定了无论他们怎么办干一定会被骂。4)为了那么一两个星期而搞那么大的系统,而其它时间都在闲着,有些可惜了,这也就是铁路才干得出来这样的事了。&&来自##50##VaiKen&
百度笔试题第三弹
笔经面经分享之百度笔试题第三弹。希望通过本帖,能够对正在找工作的同学或者将要找工作的同学提供微薄之力。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&--小站小编
结构,是关键词,是一个页面编号集合(假设资料库中每个页面有唯一编号),表示这些页面含有这个关键词。本文不详细讨论倒排索引的建立方法。
&哎编程&人人&&哎编程&&人人&&哎编程&,&,&,&,&,&;&人人&,&,&,&,&,&,&,&,将两个集合做交运算,结果是,&,&。最后,从资料库中找出、、对应的页面返回给用户就可以了。
2.3&第三个难题
页面数量非常巨大,所以一个检索的结果条目数量也非常多,例如上面&哎编程&人人&条结果。用户不可能从如此众多的结果中一一查找对自己有用的信息,所以,一个好的搜索引擎必须想办法将&质量&,并不会真的返回全部结果。),而很关心前一两页是否都是质量较高的页面,是否能满足我们的实际需求。
3&回到笔试题
题目要求从搜索得到的网页中选出一部分&重要网页&,这其实就是搜索引擎在解决第三个难题时需要做的事情。下面是两个已知的解决方案。
3.1&基于检索词的评价
算法在现代搜索引擎中仍在使用,但其已经不是评价质量的唯一指标。完整描述&比较繁琐,本文这里用一种更简单的抽象模型描述这种方法。
&&&哎编程&人人&页面出现&哎编程&&人人&页面出现&哎编程&&人人&页面的匹配度为&,页面为&,于是认为页面的重要性高于页面。很多朋友可能意识到这里的不合理性:内容较长的网页往往更可能比内容较短的网页关键词出现的次数多。因此,我们可以修改一下算法,用关键词出现次数除以页面总词数,也就是通过关键词占比作为匹配度,这样可以克服上面提到的不合理。
百度小站首页元素(例如一个&),然后其内容是&哎编程&&哎编程&人人&&哎编程&里加一万个&&,小站&&
3.2&PageRank&算法
排名运算法则(排名公式)的一部分,是用于用来标识网页的等级重要性的一种方法。
背后的概念是,每个到页面的链接都是对该页面的一次投票,被链接的越多,就意味着被其他网站投票越多。这个就是所谓的&&这个概念引自学术中一篇论文的被引述的频度即被别人引述的次数越多,一般判断这篇论文的权威性就越高。
做如下抽象:、将每个网页抽象成一个节点;、如果一个页面有链接直接链向,则存在一条有向边从到(多个相同链接不重复计算边)。因此,整个&被抽象为一张有向图。
、、、,其抽象结构如下图:
算法是基于这样一种背景思想:被用户访问越多的网页更可能质量越高,而用户在浏览网页时主要通过超链接进行页面跳转,因此我们需要通过分析超链接组成的拓扑结构来推算每个网页被访问频率的高低。最简单的,我们可以假设当一个用户停留在某页面时,跳转到页面上每个被链页面的概率是相同的。例如,上图中页面&链向、、,所以一个用户从跳转到、、的概率各为。设一共有个网页,则可以组织这样一个维矩阵:其中行列的值表示用户从页面转到页面的概率。这样一个矩阵叫做转移矩阵()。下面的转移矩阵对应上图:
值为,这里就是。按顺序将页面&为向量:
第一行分别是、、和转移到页面的概率,而的第一列分别是、、和当前的&,因此用的第一行乘以的第一列,所得结果就是页面最新&的合理估计,同理,的结果就分别代表、、、新&:
再乘以这个新的&向量,又会产生一个更新的&向量。迭代这个过程,可以证明最终会收敛,即约等于&,此时计算停止。最终的就是各个页面的&值。例如上面的向量经过几步迭代后,大约收敛在(),这就是、、、最后的&PR
当然,在实际应用情况中,PR算法要远比这里的复杂。从这个算法中我们可以看到,一个网页的PR值的高低取决于两个重要的因素:
l&有多少其他网页链接到该网页
l&链接到该网页的其他网页的R值
我认为这道题是开放性题目,并且这个问题是搜索引擎需要解决的一个重要的实际问题。如果笔试者能提出自己的解决思路,并且进行适当的分析,应该能取得很好的效果。
&&来自##17##朱元友
A*算法产品报告(小站原创研究)(上)
1&分析阶段
1.1&A*算法图形界面模块
1.1.1&功能描述
在图形平面上,已知起点、终点及障碍物,利用A*算法得到从起点到终点的最短路径。&
初始状态:
其中绿色方块代表起点;红色方块代表终点;蓝色方块代表障碍物,障碍物不能直接通行;白色方块代表普通区域,可以直接通行。&
完成状态:
计算完成后,需要得出从起点到终点的最短路径,并显示出来。黄色方块代表计算得到的最短路径。
1.1.2&界面设计&
界面如下图所示:
主要分成左右两个部分,左边是工作区域,可以在其中设置并显示起点、终点和障碍点,显示计算得到的最短路径;右边是一排按钮,各按钮的作用说明如下:
l&选择Start&Node按钮添加起点
l&选择End&Node按钮添加终点
l&选择Barrier&Node按钮添加障碍
l&选择Empty&Node按钮,添加普通地面
l&选择Calculate按钮,利用A*算法计算路径
l&选择Reset按钮,重置起点、终点及障碍物
l&选择Exit按钮,退出程序&
图形控件操作:
1.&随鼠标移动,动态跟踪鼠标当前指向的网格块:
2.&当点击右侧的按钮后,鼠标变为添加工具,再次点击网格后,网格会改变属性。
3.&网格内部只能存在一个起点,一个终点,障碍和路径可以随意添加。&
1.1.2.1&补充说明
图形空间使用Java&Swing提供的画图相关API实现。&
主界面有两个部分组成,左边是工作区域,右边是一排按钮,所以具体实现时把工作区域和按钮分别放在两个panel里面。然后把这两个panel再放到主界面frame中去。
1.1.2.2&待解决问题
暂时没有。
1.2&概要设计
1.2.1&架构图:
将程序结构分为三个组件,包括UI层组件,Server层组件和Utils层组件。
Utils层组件不依赖于任何其他组件;Server层组件只依赖于Utils层组件;UI层组件依赖于其他层组件。按照这样的结构分层,可以保证各层之间的松耦合关系。&
1.2.2&COST计算模块:
1.2.2.1&功能描述:
该模块属于Service层组件,根据UI层调用时输入的起点、终点及障碍物,利用A*算法计算出最短路径,最后将结果返回给UI层组件。
1.2.2.2&算法流程图
1.2.2.3&逻辑描述:
将开始节点放入开放列表(开始节点的F和G值都视为0)
循环重复以下步骤:
1.&在开放列表中查找具有最小F值的节点,并把查找到的节点作为当前节点;
2.&把当前节点从开放列表删除,&加入到封闭列表;
3.&对当前节点相邻的每一个节点依次执行以下步骤:
l&如果该相邻节点不可通行或者该相邻节点已经在封闭列表中,则什么操作也不执行,继续检验下一个节点;
l&如果当前节点需要跨越障碍物才能到达该相邻节点,则视该相邻节点为不可通行,继续检验下一个节点;
l&如果该相邻节点不在开放列表中,则将该节点添加到开放列表中,&并将该相邻节点的父节点设为当前节点,同时保存该相邻节点的G和F值;
l&如果该相邻节点在开放列表中,&则判断若经由当前节点到达该相邻节点的G值是否小于原来保存的G值,若小于,则将该相邻节点的父节点设为当前节点,并重新设置该相邻节点的G和F值.&
循环结束条件:&
l&当终点节点被加入到开放列表作为待检验节点时,表示路径被找到,此时应终止循环;
l&或者当开放列表为空,表明已无可以添加的新节点,而已检验的节点中没有终点节点则意味着路径无法被找到,此时也结束循环;
1.2.2.4&通信消息(接口、参数等等):&
&*&输入起点、终点及障碍物信息,并做一下初始化操作
&*&@param&start&起点信息
&*&@param&end&终点信息
&*&@param&barrier&障碍物信息
public&AStar(Node&start,&Node&end,&List&Node&&barrier)&
&*&利用A*算法查找最短路径
public&void&searchPath()&
&*&得出计算得到的最短路径,并返回给客户端
&*&@return&最短路径
&*&@throws&NoPathException&从起点到终点没有路径
public&List&Node&&getPath()&throws&NoPathException
1.2.2.5&设计心得&
刚开始的时候要明确需求,确定COST计算模块的输入和输出是什么。A*算法问题的输入是起点、终点及障碍物,输出是最短路径信息。&
在具体写算法逻辑之前,需要清楚逻辑描述中的每个步骤的意义。对于比较复杂的逻辑,基本不可能一次就写正确,因此需要反复的测试、调试和修改。&
通信接口设计应该方便客户端程序员的使用,尽量使客户端程序员不需要研究接口方法的具体实现就能明确如何调用。为了达到这个目的,可以使用如下方法:
l&接口方法命名清晰,长短不是关键,关键是让人一目了然;
l&接口方法要有正确的注释,注释包括方法注释和方法参数注释。注释应该说明方法的作用,解释设计思想,这样可以方便日后维护。
&&来自##18##朱元友、##7##向蒙
A*算法产品报告(小站原创研究)(下)
1.3&详细设计
1.3.1&类图
1.3.1.1&UI层组件类图:
1.&AStarFrame是主界面类,由于主界面有两个panel组成,分别是工作区域和一排按钮,所以AStarFrame有两个JPanel类型的成员变量,分别代表这两个panel。&
2.&SpacePanelManager负责管理工作区域所在的panel,与工作区域相关的操作有画出界面上的方格,管理panel对象的初始化,最短路径计算完毕后将其画在工作区域上。
MouseMotionListener和MouseListener是SpacePanelManager的内部类。
MouseMotionListener负责监听鼠标移动事件,用来完成随鼠标移动,动态跟踪鼠标当前指向的网格块的功能。MouseListener负责监听鼠标点击事件,用来完成设置起始点、终点、障碍点及普通地面的功能。&
3.&ButtonPanelManager负责管理按钮所在的panel,与按钮区相关的操作有管理panel对象的初始化及按钮事件的响应。
StartNodeActionListener负责监听Start&Node按钮点击事件,点击后可以在工作区域设置起点
EndNodeActionListener负责监听End&Node按钮点击事件,点击后可以在工作区域设置终点
BarrierNodeActionListener负责监听Barrier&Node按钮点击事件,点击后可以在工作区域添加障碍物
EmptyNodeActionListener负责监听Empty&Node按钮点击事件,点击后可以在工作区域添加普通地面
CalculateNodeActionListener负责监听Calculate按钮点击事件,点击后计算最短路径并显示
ResetNodeActionListener负责监听Reset按钮点击事件,点击后重置起点、终点及障碍物
ExitNodeActionListener负责监听Exit按钮点击事件,点击后退出程序
这些Listener都是ButtonPanelManager的内部类&
4.&SpacePanelManager及ButtonPanelManager被设计成单例,因为工作区域只需要被初始化一次。&
1.3.1.2&Service层类图
AStar类是执行A*算法的地方,它会根据UI层调用时输入的起点、终点及障碍物,利用A*算法计算出最短路径,最后将结果以List&Node&形式返回给UI层组件。&
Node类代表工作区域中的点。成员变量p代表该点左上角的坐标。Parent代表该点指向的父结点,FVal、GVal及HVal分别代表F、G及H值。&
NODE_TYPE是一个enum,代表所有的可能存在的点的类型,包括起点,终点,障碍点,路径上的点。它还有一个getColor方法,用来根据当前点的类型获得颜色。&
1.3.1.3&Utils层类图
NoPathException异常类代表当前从起点到终点没有可行的路径。&
NoStartOrEndNodeException异常类代表当前没有设置起点或终点就点击了Calculate按钮。
A*算法逻辑见1.2.2.2,A*算法逻辑在AStar类实现,代码如下:
public&class&AStar&{
& &&private&List&Node&&openList&=&new&ArrayList&Node&();
& &&private&List&Node&&closedList&=&new&ArrayList&Node&();&
& &&private&Node&start&=&
& &&private&Node&end&=&
& &&private&List&Node&&barrier&=&new&ArrayList&Node&();&
& &&public&final&static&int&DIAGONAL_COST&=&14;
& &&public&final&static&int&STRAIGHT_LINE_COST&=&10;&
& &&&*&输入起点、终点及障碍物信息,并做一下初始化操作
& &&&*&@param&start&起点信息
& &&&*&@param&end&终点信息
& &&&*&@param&barrier&障碍物信息
& &&public&AStar(Node&start,&Node&end,&List&Node&&barrier)&&{
&& &&&& validateInput(start,&end);
&& &&&& this.start&=&
&& &&&& this.end&=&
&& &&&& this.barrier&=&
&& &&&& initStart();
& &&private&void&initStart()&{
& &&& & start.setGVal(0);
& &&& & start.setHVal(0);
& &&&*&利用A*算法查找最短路径
& &&public&void&searchPath()&{
& &&& &&openList.add(start);
& &&& &&Node&current&=&
& &&& &&List&Node&&ajacents&=&
& && &&&while&(&!openList.isEmpty()&&&&NodeManager.isNodeListContainsNode(openList, end.getLeftTop())==-1)&{
& & &&& &&& current&=&openList.get(0);
& & &&& &&& openList.remove(0);
& & & && &&&closedList.add(current);&
& & &&& &&& ajacents&=&getAjacents(current.getLeftTop());
& & & && &&&for&(Node&node&:&ajacents)&{
& & && &&& &&&& //out&of&boundary:
& & & & && &&&& if&(NodeManager.isNodeOutOfBounds(node.getLeftTop()))&{
& & & && &&&& &
& & & & && &&&& }&
& & & &&&& &&&&&//not&walkable:
& & & &&& &&& &if&(NodeManager.isNodeListContainsNode(barrier,&node.getLeftTop())&!=&-1)&{
& & & & && &&&&
& & & & && &&&& }
& & & &&& &&& & //in&closed&list:
& & & && &&&& & if&(NodeManager.isNodeListContainsNode(closedList,&node.getLeftTop())&!=&-1)&{
& & & &&& &&& &
& & & &&& &&& & }&
& & & & && &&&& //cross&the&barrier
& & & & && &&&& if&(&crossBarrier(current,node)&)&{
& & & & &&& &&&
& & & & &&& &&& }&
& & & & &&& &&& int&index&=&NodeManager.isNodeListContainsNode(openList, & & & & &node.getLeftTop());
& & & & && &&&& //not&in&open&list:
& & & &&& &&& & if&(index&==&-1)&{
& & & &&& &&& & openList.add(node);
& & & &&& &&& & node.setParent(current);
& & & &&& &&& & node.setGVal(current.getGVal()&+&calculateAjacentGVal(node,&current));
& & & && &&&& & node.setHVal(calculateAjacentHVal(node));
& & & && &&&& & }&else&{//&in&open&list
& & & &&& &&& & & & int&ajacentGVal&=&openList.get(index).getGVal();
& & & &&& &&& & & & int&newGVal&=&current.getGVal()&+&calculateAjacentGVal(node,&current);
& & & && &&&& & & & if&(newGVal&&&ajacentGVal)&{
& & & &&& &&& & & & openList.get(index).setParent(current);
& & & &&& &&& & & & openList.get(index).setGVal(newGVal);
& & & &&& &&& & & & }
& & & &&& &&& & }
& & & && &&&}&
& && &&&& & Collections.sort(openList,&new&AStarComparable());
& &&private&boolean&crossBarrier(Node&current,&Node&node)&{
&&& &&& boolean&isCross&=&
&&& &&& Point&p1&=&current.getLeftTop();
& && &&&Point&p2&=&node.getLeftTop();&
& && &&&Point&chkPoint1&=&new&Point(p1.x,&p2.y);&
& && &&&Point&chkPoint2&=&new&Point(p2.x,&p1.y);&& &&
&&& &&&&if&(NodeManager.isNodeListContainsNode(barrier,&chkPoint1)!=-1
||&NodeManager.isNodeListContainsNode(barrier,&chkPoint2)!=-1)&{
& && &&&isCross&=&
&&& &&&&}&
& &&& &&return&isC
& &&&*&得出计算得到的最短路径,并返回给客户端
& &&&*&@return&最短路径
& &&&*&@throws&NoPathException&从起点到终点没有路径
& &&public&List&Node&&getPath()&throws&NoPathException&{
& &&& &&int&index&=&NodeManager.isNodeListContainsNode(openList,&& &&& &&end.getLeftTop());
& && &&&if&(&index==-1)&{
& && &&&throw&new&NoPathException();
& && &&&}&
& && &&&List&Node&&resultPath&=&new&ArrayList&Node&();
& && &&&Node&endNode&=&openList.get(index);
& && &&&while&(&!endNode.getParent().getLeftTop().equals(start.getLeftTop())&)&{
& && &&&resultPath.add(endNode.getParent());
& && &&&endNode&=&endNode.getParent();
& && &&&}&
& &&& &&return&resultP
& &&private&int&calculateAjacentHVal(Node&node)&{
&&& &&&Point&p1&=&node.getLeftTop();
& && &&&Point&p2&=&end.getLeftTop();
&&& &&&&int&gap&=&Math.abs(p1.x&-&p2.x)/NODE_SIDE_LENGH&+&Math.abs(p1.y&-&p2.y)/NODE_SIDE_LENGH;&
& && &&&return&gap&*&STRAIGHT_LINE_COST;
& && &&&}&
& &&private&int&calculateAjacentGVal(Node&node1,&Node&node2)&{
&&& &&&&int&cost&=&0;
& && &&&if&(isDiagonal(node1,&node2))&{
& && &&&cost&=&DIAGONAL_COST;
& && &&&}&else&{
& &&& &&cost&=&STRAIGHT_LINE_COST;
& &&& &&return&
& &&private&boolean&isDiagonal(Node&node1,&Node&node2)&{
&&& &&&&boolean&isDiagonal&=&
&&& &&&&Point&p1&=&node1.getLeftTop();
& && &&&Point&p2&=&node2.getLeftTop();
&&& &&&&if&(Math.abs(p1.x&-&p2.x)==NODE_SIDE_LENGH
&&&Math.abs(p1.y&-&p2.y)==NODE_SIDE_LENGH)&{
& && &&&isDiagonal&=&
& &&& &&return&isD
& &&private&List&Node&&getAjacents(Point&p)&{
&&& &&&&List&Node&&ajacents&=&new&ArrayList&Node&();
&&& &&&&ajacents.add(new&Node(p.x,p.y-NODE_SIDE_LENGH));//top
& && &&&ajacents.add(new&Node(p.x,p.y+NODE_SIDE_LENGH));//bottom
& && &&&ajacents.add(new&Node(p.x-NODE_SIDE_LENGH,p.y));//left
& && &&&ajacents.add(new&Node(p.x+NODE_SIDE_LENGH,p.y));//right
& &&& &&ajacents.add(new&Node(p.x-NODE_SIDE_LENGH,p.y-NODE_SIDE_LENGH));//left&top
&&& &&&&ajacents.add(new&Node(p.x+NODE_SIDE_LENGH,p.y-NODE_SIDE_LENGH));//right&top
&&& &&&&ajacents.add(new&Node(p.x-NODE_SIDE_LENGH,p.y+NODE_SIDE_LENGH));//left&bottom
&&& &&&&ajacents.add(new&Node(p.x+NODE_SIDE_LENGH,p.y+NODE_SIDE_LENGH));//right&bottom
&& &&&&&return&
& &&private&void&validateInput(Node&start,&Node&end)&throws&NoStartOrEndNodeException&{
&&& &&&&if&(start&==&null)&{
&& &&&&&throw&new&NoStartOrEndNodeException(&start&);
&&& &&&&if&(end&==&null)&{
& &&& &&throw&new&NoStartOrEndNodeException(&end&);
& &&private&class&AStarComparable&implements&Comparator&Node&&{
& &&& &&public&int&compare(Node&o1,&Node&o2)&{
& &&& &&return&o1.getFVal()&-&o2.getFVal();
设计的过程中可以间接的了解到其他的最短路径算法,A*算法作为最短路径算法的一种,有着它独特的优势,通过查阅资料,我们找到了一个整理的非常完善的A*算法的帖子,对比了A*算法与其他算法之间的优势,虽然是英文的,但是可以通过借助翻译软件我们可以大致读懂,给大家分享一下:
其次,关于启发,有不同的计算方法,即H值的计算公式问题,通常,我们采用的是曼哈顿距离,但是我们有时还要了解其他的计算方法:
h(n)&=&D&*&(abs(n.x-goal.x)&+&abs(n.y-goal.y))
详情参见:
&&来自##18##朱元友、##7##向蒙&&
三星凭什么赶超苹果?
作者:eoe移动开发门户 来源:驱动之家&导读:作为&苹果&的学徒和核心部件供应商,三星短短数年间在智能手机领域后来居上,成为世界第一,究竟是怎么做到的?&  &逆向工程&和&数字融合战略&,为三星在电子领域奠定了核心竞争力,而在当&苹果&学徒的过程中,三星又学得如此彻底,以至于在成为智能手机老大的同时,也陷入了与苹果的诸多专利官司之中。  日,三星股价创下历史新高,当日上涨1.4%至143.7万韩元(约合1325美元)。2012年以来,三星已经累计上涨36%,市值达到212万亿韩元(约合1950亿美元)。  而它的主要竞争对手苹果公司则要惨淡得多,其股价自日创下705美元的高点至今,在两个月内已累计下跌约20%,目前为571美元。  这样的反差,自然是以三星2012年在智能手机领域的骄人业绩作为背书的。据美国权威的IT研究与顾问咨询公司Gartner统计,月全球智能手机市场规模为16920万部,其中三星电子公司售出智能手机5500万部,苹果公司的iPhone售出2360万部。从份额来看,三星占32.5%,高居全球榜首,而苹果占14%。  作为&苹果&的学徒和核心部件供应商,三星短短数年间在智能手机领域后来居上,成为世界第一,究竟是怎么做到的?  &逆向工程&  在电子领域,三星进入每一项业务时都比其主要竞争者迟得多,比如家电业务比松下迟了51年,半导体业务比Intel迟了10年,而在以手机为主的通讯业务上比诺基亚迟了足足122年。  但据多家市场研究公司数据显示,三星在存储器和显示屏领域,市场占有率全球第一,电视业务也已经连续5年把持了全球销量冠军,而三星的手机业务更是在2012年顺利地从诺基亚手中夺取了世界第一手机厂商的宝座,同时也成功超越苹果,成为世界第一智能手机厂商。  三星后来居上,得益于它的&逆向工程&。一般而言,进入这样的高科技领域,都要从最基本的研发开始,但是,考虑到时间和试错成本太高,三星一开始就采用了一个与同行完全不同的策略&&通过支付专利金引入技术,然后以模仿的方式学习他人的技术,再改造成适合三星使用的研发方向。  在开始阶段,这一方式让三星吃了不少苦头。三星刚刚投资DRAM内存时,由于市场的不景气,三星累计亏损达3亿美元。在这种大背景下,Intel等美国公司退出该领域,日本企业则缩减投资规模和生产能力。  而三星不但没有退出,反而采取自杀式的反周期投资&&继续扩大产能,并开发更大容量的DRAM。1987年,行业出现转折。美国政府发起针对日本半导体企业的反倾销诉讼案,美国政府和日本企业达成自动出口限制协议,日本企业缩减了向美国的出口。很快DRAM价格回升,三星开始盈利。  投资液晶面板时,三星也是不按常理出牌。1996年,液晶面板行业出现衰退,而三星却在1996年建成第一条液晶面板第3代技术生产线,赶上了日本企业的生产能力。1997年亚洲金融危机爆发后,三星再一次采取了反周期的投资法,投资扩建液晶面板生产线,并在技术上已经全面领先日本企业。  而在亚洲金融危机之后,三星极具前瞻性地发现是,他们认准了电脑、手机、CD机等产品共有的核心技术:半导体元件、大屏幕液晶显示器、显示驱动程序和芯片组,以及移动电话技术等。  1999年,三星对外宣布了三星电子&数字融合&战略,即在未来成为&数字融合革命的一个领导者&的计划。这一战略能够实施,也得益于三星的多元化布局,从半导体到计算机显示器,从TFT-LCD显示屏到彩色显像管,三星在很多领域都是行业的领导者。  实际上,三星如今的对手,苹果公司的诸多产品,从iPod到iPhone,其核心部件&&CPU、液晶显示屏等,大多来自三星。一项分析显示,三星电子供应的CPU约占iPhone价格构成的8.4%。  学习&苹果&  5年前,苹果刚刚推出iPhone的时候,没有人会相信iPhone会获得如此巨大的成功,也并不是所有人都能够清晰地预见到智能手机未来的发展趋势。当时的手机界大佬诺基亚在看到iPhone时,更是不屑一顾地认为iPhone不值一提。  一开始,三星从苹果的&打工仔&做起,帮苹果生产iPad、iPhone上的LED屏幕和处理器芯片,成为苹果最大的闪存和元器件供应商。  作为苹果公司的竞争对手,从中兴到华为,从摩托罗拉到三星,起初都选择了用&机海战术&与iPhone竞争。  但2010年之后,三星的战略就发生了变化。三星中国公司的一位内部员工告诉《南方周末》记者,在此之前,他们研究的目标主要是诺基亚,所有的努力都集中于翻盖、直板和滑盖元素,但三星的用户体验与苹果iPhone对比时,却存在天壤之别。据这位员工透露,危机感和紧迫感促使三星的设计师和工程师采用了最符合iPhone外观和感觉的理念。  2010年,三星推出了首款搭载Google Android系统和自家TouchWiz用户界面的Galaxy S手机。与以往同时推出多款机型不同的是,这一次,三星并没有推出多个型号,而只将这一款手机作为自家的旗舰产品,几乎与苹果的战略如出一辙。  一年后,三星又推出了Galaxy S II,2012年再接再厉,推出Galaxy S III,这款2012年5月末推出的手机,仅在100天之内便销售2000万部,创造了&史上最短时间最大销量&的纪录,相当于平均每天销售20万部。  2012年第二季度,三星的营业利润达到了创纪录的58.6亿美元,其中,三星手机业务的净利润高达36.5亿美元,占到了总利润的62.3%,并且与苹果联手把持了全球智能手机市场90%的利润。  一山不容二虎,三星的崛起迅速引来了苹果的反击。2011年4月,苹果指控三星电子侵犯了其智能手机多项专利。在经过长达一年多的诉讼后,三星最终败诉,被判向苹果支付高达10.49亿美元的罚金。  但据韩国媒体报道,自从在与苹果的专利大战中遇挫之后,三星集团向旗下三星电子、三星生命、三星物产等企业下达命令,要求全体员工的上班时间提前至早6:30(在这之前是早7:00),希望借此让员工认识到三星正在处于危机中,增强员工的危机意识。  三星的麻烦并没有结束。目前它与苹果在全球10个国家卷入了专利诉讼案件。&  &&##28##光伟&
千万要避免的五种程序注释方式(转)
& & 你是否有过复查程序时发现有些注释毫无用处?程序注释是为了提高代码的可读性,为了让原作者以外的其他开发人员更容易理解这段程序。
我把这些让人郁闷的注释方式归为了五类,同时把写出这些注释的程序员也归为了五类。你感觉自己属于其中的哪一种类型?如果你有兴趣的话可以读一下另外一篇文章&五种程序员(英文),和这篇讲到的五种程序员对比一下。
1.&高傲的程序员
public&class&Program
static&void&Main(string[]&args)
string&message&=&&Hello&World!&;&&//&07/24/2010&Bob
Console.WriteLine(message);&//&07/24/2010&Bob
message&=&&I&am&so&proud&of&this&code!&;&//&07/24/2010&Bob
Console.WriteLine(message);&//&07/24/2010&Bob
2.&过时的程序员
public&class&Program
static&void&Main(string[]&args)
/*&这段程序已经不再有用
*&因为我们发现千年虫问题只是一场虚惊
*&我们的系统不会恢复到1/1/1900&*/
//DateTime&today&=&DateTime.T
//if&(today&==&new&DateTime())
//&&&&today&=&today.AddYears(100);
//&&&&string&message&=&&The&date&has&been&fixed&for&Y2K.&;
//&&&&Console.WriteLine(message);
如果一段程序不再有用(比如废弃了),那就删了它吧&&不要被几行没用的注释搞的程序混乱不堪。即使你可能以后重用这段代码,你也可以使用版本控制系统,用它把你的程序恢复到以前的样子。
3.&天真的程序员
public&class&Program
static&void&Main(string[]&args)
/*&这个程序是用来在屏幕上
*&循环打印1百万次&I&Rule!&
*&每次输出一行。循环计数
*&从0开始,每次加1。
*&当计数器等于1百万时,
*&循环就会停止运行*/
for&(int&i&=&0;&i&&&1000000;&i++)
Console.WriteLine(&I&Rule!&);
基本的编程语法规则我们大家都知道&&我们不需要&编程入门&。你不需要浪费时间来解释一个显而易见的东西,我们更希望知道的是你的程序功能&&那是浪费空间了。
4.&天真的程序员
public&class&Program
static&void&Main(string[]&args)
/*&有一天我在大街上的一家星巴克里
*&和销售部的Jim讨论问题,他告诉我
*&销售代表是依据以下的比例提取佣金的。
*&周五:&25%
*&周三:&15%
*&其它日期:&5%
*&我是否告诉你过我点了一个卡拉梅
*&铁咖啡和两份的Espresso?
double&price&=&5.00;
double&commissionR
if&(DateTime.Today.DayOfWeek&==&DayOfWeek.Friday)
commissionRate&=&.25;
else&if&(DateTime.Today.DayOfWeek&==&DayOfWeek.Wednesday)
commissionRate&=&.15;
commissionRate&=&.05;
commission&=&price&*&commissionR
5.&天真的程序员
public&class&Program
static&void&Main(string[]&args)
//TODO:&将来我会修复这个问题&&&07/24/1995&Bob
/*&我知道这个问题很难解决而且
*&我现在依赖于这个Contains函数,但
*&我以后会用一种更有意义,更
*&优雅的方式打印这段代码。
*&我只是现在没时间。
string&message&=&&An&error&has&occurred&;
if(message.Contains(&error&))
throw&new&Exception(message);
这种注释是一种集大成者,它包含了上面所说的注释的所有问题。TODO注释在一个项目最初的开发阶段是非常有用的,但这个注释看起来是在好几年前的产品程序里的&&它证明了程序有问题。如果程序有问题需要解决,马上解决,不要拖到日后再解决。
你是否在自己的代码中看到了其它类型多余或扰人的注释?请不吝分享。
&&来自##20##王韩杰
53641人关注
53641人关注
站长在关注
说的太好了,我顶!
Copyright & 2014 www.51yue.net Corporation, All Rights Reserved
Processed in 0.1845 second(s), 3 db_queries,
0 rpc_queries

我要回帖

更多关于 魔兽世界音乐文件 的文章

 

随机推荐