??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品久久久久蜜芽,97超级碰碰碰碰久久久久,久久久久成人精品无码中文字幕
http://www.shnenglu.com/softko/category/14124.html淡薄名利,修nL?/description>zh-cn Wed, 22 Jun 2011 09:08:07 GMT Wed, 22 Jun 2011 09:08:07 GMT 60 各种排序法介绍 http://www.shnenglu.com/softko/archive/2011/06/17/148828.htmleircQ eircQ Fri, 17 Jun 2011 00:09:00 GMT http://www.shnenglu.com/softko/archive/2011/06/17/148828.html http://www.shnenglu.com/softko/comments/148828.html http://www.shnenglu.com/softko/archive/2011/06/17/148828.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/148828.html http://www.shnenglu.com/softko/services/trackbacks/148828.html 排序法是一U基本ƈ且常用的法。由于实际工作中处理的数量巨大,所以排序算法对法本n的速度要求很高?br /> 而一般我们所谓的法的性能主要是指法的复杂度Q一般用OҎ来表C。在后面我将l出详细的说明?br /> 对于排序的算法我惛_做一点简单的介绍Q也是给q篇文章理一个提UӀ?br /> 我将按照法的复杂度Q从单到难来分析法?br /> W一部分是简单排序算法,后面你将看到他们的共同点是算法复杂度为O(N*N)Q因为没有用word,所以无法打Z标和下标Q?br /> W二部分是高U排序算法,复杂度ؓO(Log2(N))。这里我们只介绍一U算法。另外还有几U算法因为涉及树与堆的概念,所以这里不于讨论?br /> W三部分cM动脑{。这里的两种法q不是最好的Q甚x最慢的Q,但是法本n比较奇特Q值得参考(~程的角度)。同时也可以让我们从另外的角度来认识q个问题?br /> W四部分是我送给大家的一个餐后的甜点——一个基于模板的通用快速排序。由于是模板函数可以对Q何数据类型排序(抱歉Q里面用了一些论坛专家的呢称Q? 现在Q让我们开始吧Q? 一、简单排序算? ׃E序比较单,所以没有加什么注释。所有的E序都给Z完整的运行代码,q在我的VC环境下运行通过。因为没有涉及MFC和WINDOWS的内容,所以在BORLAND C++的^C应该也不会有什么问题的。在代码的后面给Zq行q程C意Q希望对理解有帮助? 1.冒法: q是最原始Q也是众所周知的最慢的法了。他的名字的由来因ؓ它的工作看来象是冒Q? #include <iostream.h> void BubbleSort(int* pData,int Count) { int iTemp; for(int i=1;i<Count;i++) { for(int j=Count-1;j>=i;j--) { if(pData[j]<pData[j-1]) { iTemp = pData[j-1]; pData[j-1] = pData[j]; pData[j] = iTemp; } } } } void main() { int data[] = {10,9,8,7,6,5,4}; BubbleSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 倒序(最p情? W一轮:10,9,8,7->10,9,7,8->10,7,9,8->7,10,9,8(交换3? W二轮:7,10,9,8->7,10,8,9->7,8,10,9(交换2? W一轮:7,8,10,9->7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 其他Q? W一轮:8,10,7,9->8,10,7,9->8,7,10,9->7,8,10,9(交换2? W二轮:7,8,10,9->7,8,10,9->7,8,10,9(交换0? W一轮:7,8,10,9->7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 上面我们l出了程序段Q现在我们分析它Q这里,影响我们法性能的主要部分是循环和交换, 昄Q次数越多,性能p差。从上面的程序我们可以看出@环的ơ数是固定的Qؓ1+2+...+n-1? 写成公式是1/2*(n-1)*n? 现在注意Q我们给出OҎ的定义: 若存在一帔RK和v点n0Q当n>=n0Ӟ有f(n)<=K*g(n),则f(n) = O(g(n))。(呵呵Q不要说没学好数学呀Q对于编E数学是非常重要的!Q!Q? 现在我们来看1/2*(n-1)*nQ当K=1/2Qn0=1Qg(n)=n*nӞ1/2*(n-1)*n<=1/2*n*n=K*g(n)。所?n)=O(g(n))=O(n*n)。所以我们程序@环的复杂度ؓO(n*n)? 再看交换。从E序后面所跟的表可以看刎ͼ两种情况的@环相同,交换不同。其实交换本w同数据源的有序E度有极大的关系Q当数据处于倒序的情冉|Q?交换ơ数同@环一P每次循环判断都会交换Q,复杂度ؓO(n*n)。当数据为正序,不会有交换。复杂度为O(0)。ؕ序时处于中间状态。正是由于这?的原因,我们通常都是通过循环ơ数来对比算法? 2.交换法: 交换法的E序最清晰单,每次用当前的元素一一的同其后的元素比较ƈ交换? #include <iostream.h> void ExchangeSort(int* pData,int Count) { int iTemp; for(int i=0;i<Count-1;i++) { for(int j=i+1;j<Count;j++) { if(pData[j]<pData[i]) { iTemp = pData[i]; pData[i] = pData[j]; pData[j] = iTemp; } } } } void main() { int data[] = {10,9,8,7,6,5,4}; ExchangeSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 倒序(最p情? W一轮:10,9,8,7->9,10,8,7->8,10,9,7->7,10,9,8(交换3? W二轮:7,10,9,8->7,9,10,8->7,8,10,9(交换2? W一轮:7,8,10,9->7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 其他Q? W一轮:8,10,7,9->8,10,7,9->7,10,8,9->7,10,8,9(交换1? W二轮:7,10,8,9->7,8,10,9->7,8,10,9(交换1? W一轮:7,8,10,9->7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 从运行的表格来看Q交换几乎和冒一L。事实确实如此。@环次数和冒一样也?/2*(n-1)*nQ所以算法的复杂度仍然是O(n*n)。由于我们无法给出所有的情况Q所以只能直接告诉大家他们在交换上面也是一Lp糕Q在某些情况下稍好,在某些情况下E差Q? 3.选择法: 现在我们l于可以看到一点希望:选择法,q种Ҏ提高了一Ҏ能Q某些情况下Q? q种ҎcM我们Zؓ的排序习惯:从数据中选择最的同第一个g换,在从省下的部分中选择最的与第二个交换Q这样往复下厅R? #include <iostream.h> void SelectSort(int* pData,int Count) { int iTemp; int iPos; for(int i=0;i<Count-1;i++) { iTemp = pData[i]; iPos = i; for(int j=i+1;j<Count;j++) { if(pData[j]<iTemp) { iTemp = pData[j]; iPos = j; } } pData[iPos] = pData[i]; pData[i] = iTemp; } } void main() { int data[] = {10,9,8,7,6,5,4}; SelectSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 倒序(最p情? W一轮:10,9,8,7->(iTemp=9)10,9,8,7->(iTemp=8)10,9,8,7->(iTemp=7)7,9,8,10(交换1? W二轮:7,9,8,10->7,9,8,10(iTemp=8)->(iTemp=8)7,8,9,10(交换1? W一轮:7,8,9,10->(iTemp=9)7,8,9,10(交换0? 循环ơ数Q?? 交换ơ数Q?? 其他Q? W一轮:8,10,7,9->(iTemp=8)8,10,7,9->(iTemp=7)8,10,7,9->(iTemp=7)7,10,8,9(交换1? W二轮:7,10,8,9->(iTemp=8)7,10,8,9->(iTemp=8)7,8,10,9(交换1? W一轮:7,8,10,9->(iTemp=9)7,8,9,10(交换1? 循环ơ数Q?? 交换ơ数Q?? 遗憾的是法需要的循环ơ数依然?/2*(n-1)*n。所以算法复杂度为O(n*n)? 我们来看他的交换。由于每ơ外层@环只产生一ơ交换(只有一个最|。所以f(n)<=n 所以我们有f(n)=O(n)?br />所以,在数据较q时候,可以减少一定的交换ơ数? 4.插入法: 插入法较为复杂,它的基本工作原理是抽出牌Q在前面的牌中寻扄应的位置插入Q然后l下一? #include <iostream.h> void InsertSort(int* pData,int Count) { int iTemp; int iPos; for(int i=1;i<Count;i++) { iTemp = pData[i]; iPos = i-1; while((iPos>=0) && (iTemp<pData[iPos])) { pData[iPos+1] = pData[iPos]; iPos--; } pData[iPos+1] = iTemp; } } void main() { int data[] = {10,9,8,7,6,5,4}; InsertSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 倒序(最p情? W一轮:10,9,8,7->9,10,8,7(交换1?(循环1? W二轮:9,10,8,7->8,9,10,7(交换1?(循环2? W一轮:8,9,10,7->7,8,9,10(交换1?(循环3? 循环ơ数Q?? 交换ơ数Q?? 其他Q? W一轮:8,10,7,9->8,10,7,9(交换0?(循环1? W二轮:8,10,7,9->7,8,10,9(交换1?(循环2? W一轮:7,8,10,9->7,8,9,10(交换1?(循环1? 循环ơ数Q?? 交换ơ数Q?? 上面l尾的行为分析事实上造成了一U假象,让我们认U算法是单算法中最好的Q其实不是,因ؓ其@环次数虽然ƈ不固定,我们仍可以用O?法。从上面的结果可以看出,循环的次数f(n)<= 1/2*n*(n-1)<=1/2*n*n。所以其复杂度仍为O(n*n)Q这里说明一下,其实如果不是Z展示q些单排序的不同Q交换次C?可以q样推导Q。现在看交换Q从外观上看Q交换次数是O(n)Q推导类似选择法)Q但我们每次要进行与内层循环相同ơ数?#8216;=’操作。正常的一ơ交换我?需要三?#8216;=’Q而这里显然多了一些,所以我们浪费了旉? 最l,我个为,在简单排序算法中Q选择法是最好的? 二、高U排序算法: 高排序法中我们将只介l这一U,同时也是目前我所知道Q我看过的资料中Q的最快的? 它的工作看v来仍然象一个二叉树。首先我们选择一个中间值middleE序中我们用数l中间|然后把比它小的放在左边,大的攑֜双Q具体的实现是从两边找,扑ֈ一对后交换Q。然后对两边分别使用q个q程Q最Ҏ的方?#8212;—递归Q? 1.快速排序: #include <iostream.h> void run(int* pData,int left,int right) { int i,j; int middle,iTemp; i = left; j = right; middle = pData[(left+right)/2]; //求中间? do{ while((pData[i]<middle) && (i<right))//从左扫描大于中值的? i++; while((pData[j]>middle) && (j>left))//从右扫描大于中值的? j--; if(i<=j)//扑ֈ了一对? { //交换 iTemp = pData[i]; pData[i] = pData[j]; pData[j] = iTemp; i++; j--; } }while(i<=j);//如果两边扫描的下标交错,停止(完成一ơ) //当左辚w分有?left<j)Q递归左半? if(left<j) run(pData,left,j); //当右辚w分有?right>i)Q递归叛_? if(right>i) run(pData,i,right); } void QuickSort(int* pData,int Count) { run(pData,0,Count-1); } void main() { int data[] = {10,9,8,7,6,5,4}; QuickSort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } q里我没有给为的分析Q因个很单,我们直接来分析算法:首先我们考虑最理想的情? 1.数组的大是2的幂Q这样分下去始终可以?整除。假设ؓ2的kơ方Q即k=log2(n)? 2.每次我们选择的值刚好是中间|q样Q数l才可以被等分? W一层递归Q@环nơ,W二层@?*(n/2)...... 所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n 所以算法复杂度为O(log2(n)*n) 其他的情况只会比q种情况差,最差的情况是每ơ选择到的middle都是最值或最大|那么他将变成交换法(׃使用了递归Q情冉|p)。但是你认ؓq种情况发生的几率有多大Q?呵呵Q你完全不必担心q个问题。实践证明,大多数的情况Q快速排序L最好的? 如果你担心这个问题,你可以用堆排序Q这是一U稳定的O(log2(n)*n)法Q但是通常情况下速度要慢 于快速排序(因ؓ要重l堆Q? 三、其他排? 1.双向冒Q? 通常的冒泡是单向的,而这里是双向的,也就是说q要q行反向的工作? 代码看v来复杂,仔细理一下就明白了,是一个来回震荡的方式? 写这D代码的作者认样可以在冒的基上减一些交换(我不q么认ؓQ也许我错了Q? 反正我认是一D|的代码Q值得一看? #include <iostream.h> void Bubble2Sort(int* pData,int Count) { int iTemp; int left = 1; int right =Count -1; int t; do { //正向的部? for(int i=right;i>=left;i--) { if(pData[i]<pData[i-1]) { iTemp = pData[i]; pData[i] = pData[i-1]; pData[i-1] = iTemp; t = i; } } left = t+1; //反向的部? for(i=left;i<right+1;i++) { if(pData[i]<pData[i-1]) { iTemp = pData[i]; pData[i] = pData[i-1]; pData[i-1] = iTemp; t = i; } } right = t-1; }while(left<=right); } void main() { int data[] = {10,9,8,7,6,5,4}; Bubble2Sort(data,7); for (int i=0;i<7;i++) cout<<data[i]<<" "; cout<<"\n"; } 2.SHELL排序 q个排序非常复杂Q看了程序就知道了? 首先需要一个递减的步长,q里我们使用的是9???Q最后的步长必须?Q? 工作原理是首先对盔R9-1个元素的所有内Ҏ序,然后再用同LҎ对相?-1个元素的排序以次cL? #include <iostream.h> void ShellSort(int* pData,int Count) { int step[4]; step[0] = 9; step[1] = 5; step[2] = 3; step[3] = 1; int iTemp; int k,s,w; for(int i=0;i<4;i++) { k = step[i]; s = -k; for(int j=k;j<Count;j++) { iTemp = pData[j]; w = j-k;//求上step个元素的下标 if(s ==0) { s = -k; s++; pData[s] = iTemp; } while((iTemp<pData[w]) && (w>=0) && (w<=Count)) { pData[w+k] = pData[w]; w = w-k; } pData[w+k] = iTemp; } } } void main() { int data[] = {10,9,8,7,6,5,4,3,2,1,-10,-1}; ShellSort(data,12); for (int i=0;i<12;i++) cout<<data[i]<<" "; cout<<"\n"; } 呵呵Q程序看h有些头疼。不q也不是很难Q把s==0的块Lp村֤了,q里是避免?步长造成E序异常而写的代码。这个代码我认ؓ很值得一看? q个法的得名是因ؓ其发明者的名字D.L.SHELL。依照参考资料上的说法:“׃复杂的数学原因避免?的幂ơ步长,它能降低法效率?#8221;另外法的复杂度为n?.2ơ幂。同样因为非常复杂ƈ“出本书讨论范围”的原因(我也不知道过E)Q我们只有结果了? 最后,希望大家愉快的编E。有什么意见,l我提吧Q? ]]> Hash 法及其应用(? http://www.shnenglu.com/softko/archive/2010/12/02/135309.htmleircQ eircQ Thu, 02 Dec 2010 15:08:00 GMT http://www.shnenglu.com/softko/archive/2010/12/02/135309.html http://www.shnenglu.com/softko/comments/135309.html http://www.shnenglu.com/softko/archive/2010/12/02/135309.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/135309.html http://www.shnenglu.com/softko/services/trackbacks/135309.html 期:2004-07-30] 来源Q?a target="_blank" style="color: rgb(65, 81, 154); text-decoration: none; ">CSDN 作者: [字体Q?a style="color: rgb(65, 81, 154); text-decoration: none; ">?/a> ?/a> ?/a>] --------------- 什么是 Hash Hash 的重要特?nbsp; Hash 函数的实?nbsp; 主要?Hash 法 Hash 法的安全问?nbsp; Hash 法的应?nbsp; l??nbsp; ---------------
HashQ一般翻译做“散列”Q也有直接音译ؓ"哈希"的,是把Q意长度的输入Q又叫做预映, pre-imageQ,通过散列法Q变换成固定长度的输出,该输出就是散列倹{这U{换是一U压~映,也就是,散列值的I间通常q小于输入的I间Q不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入倹{?/p>
数学表述为:h = H(M) Q其中H( )--单向散列函数QM--L长度明文Qh--固定长度散列倹{?/p>
在信息安全领域中应用的Hash法Q还需要满_他关键特性:
W一当然是单向?one-way)Q从预映,能够单迅速的得到散列|而在计算上不可能构造一个预映射Q其散列结果等于某个特定的散列|x造相应的M=H-1(h)不可行。这P散列值就能在l计上唯一的表征输入|因此Q密码学上的 Hash 又被UCؓ"消息摘要(message digest)"Q就是要求能方便的将"消息"q行"摘要"Q但?摘要"中无法得到比"摘要"本n更多的关?消息"的信息?/p>
W二是抗冲突?collision-resistant)Q即在统计上无法产生2个散列值相同的预映。给定MQ计上无法扑ֈM'Q满H(M)=H(M') Q此谓弱抗冲H性;计算上也难以L一对Q意的M和M'Q满H(M)=H(M') Q此谓强抗冲H性。要?强抗冲突?主要是ؓ了防范所?生日d(birthday attack)"Q在一?0人的团体中,你能扑ֈ和你生日相同的h的概率是2.4%Q而在同一团体中,?人生日相同的概率?1.7%。类似的Q当预映的I间很大的情况下Q算法必L_的强度来保证不能L扑ֈ"相同生日"的h?/p>
W三是映分布均匀性和差分分布均匀性,散列l果中,?0 ?bit 和ؓ 1 ?bit Q其L应该大致相等Q输入中一?bit 的变化,散列l果中将有一半以上的 bit 改变Q这又叫?雪崩效应(avalanche effect)"Q要实现使散列结果中出现 1bit 的变化,则输入中臛_有一半以上的 bit 必须发生变化。其实质是必M输入中每一?bit 的信息,量均匀的反映到输出的每一?bit 上去Q输Z的每一?bitQ都是输入中可能多 bit 的信息一起作用的l果?/p>
Damgard ?Merkle 定义了所?#8220;压羃函数(compression function)”Q就是将一个固定长度输入,变换成较短的固定长度的输出,q对密码学实践上 Hash 函数的设计生了很大的媄响。Hash函数是被设计ؓZ通过特定压羃函数的不断重?#8220;压羃”输入的分l和前一ơ压~处理的l果的过E,直到整个消息都被压羃完毕Q最后的输出作ؓ整个消息的散列倹{尽还~Z严格的证明,但绝大多C界的研究者都同意Q如果压~函数是安全的,那么以上qŞ式散列Q意长度的消息也将是安全的。这是所?Damgard/Merkle l构Q?/p>
在下图中QQ意长度的消息被分拆成W合压羃函数输入要求的分l,最后一个分l可能需要在末尾M特定的填充字节,q些分组被序处理Q除了第一个消息分l将与散列初始化g起作为压~函数的输入外,当前分组和前一个分l的压羃函数输出一赯作ؓq一ơ压~的输入Q而其输出又将被作Z一个分l压~函数输入的一部分Q直到最后一个压~函数的输出Q将被作为整个消息散列的l果?/p>
MD5 ?SHA1 可以说是目前应用最q泛的Hash法Q而它们都是以 MD4 为基设计的?/p>
1) MD4 MD4(RFC 1320)?MIT ?Ronald L. Rivest ?1990 q设计的QMD ?Message Digest 的羃写。它适用?2位字长的处理器上用高速Y件实?-它是Z 32 位操作数的位操作来实现的。它的安全性不像RSA那样Z数学假设Q尽?Den Boer、Bosselaers ?Dobbertin 很快q分析和差分成功的d了它3轮变换中?2 轮,证明了它q不像期望的那样安全Q但它的整个法q没有真正被破解q,Rivest 也很快进行了改进?/p>
下面是一些MD4散列l果的例子:
MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0 MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24 MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d MD4 ("message digest") = d9130a8164549fe818874806e1c7014b MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 043f8582f241db351ce627e153e7f0e4 MD4 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
2) MD5 MD5(RFC 1321)?Rivest ?991q对MD4的改q版本。它对输入仍?12位分l,其输出是4?2位字的联,?MD4 相同。它较MD4所做的改进是:
1) 加入了第四轮 2) 每一步都有唯一的加法常敎ͼ 3) W二轮中的G函数?(X ?Y) ?(X ?Z) ?(Y ?Z)) 变ؓ ((X ?Z) ?(Y ?~Z))以减其对称性; 4) 每一步都加入了前一步的l果Q以加快"雪崩效应"Q?nbsp; 5) 改变了第2轮和W?轮中讉K输入子分l的序Q减了形式的相似程度; 6) q似优化了每轮的循环左移位移量,以期加快"雪崩效应"Q各轮的循环左移都不同?nbsp; 管MD5比MD4来得复杂Qƈ且速度较之要慢一点,但更安全Q在抗分析和抗差分方面表现更好?/p>
消息首先被拆成若q个512位的分组Q其中最?12位一个分l是“消息?填充字节(100…0)+64 位消息长?#8221;Q以保对于不同长度的消息,该分l不相同?4位消息长度的限制D了MD5安全的输入长度必d?64bitQ因为大?4位的长度信息被忽略。??2位寄存器字初始化为A=0x01234567QB=0x89abcdefQC=0xfedcba98QD=0x76543210Q它们将始终参与q算qŞ成最l的散列l果?/p>
接着各个512位消息分l以16?2位字的Ş式进入算法的d@环,512位消息分l的个数据决定了循环的次数。主循环?轮,每轮分别用到了非U性函?/p>
F(X, Y, Z) = (X ?Y) ?(~X ?Z) G(X, Y, Z) = (X ?Z) ?(Y ?~Z) H(X, Y, Z) =X ⊕ Y ⊕ Z I(X, Y, Z) = X ⊕ (Y ?~Z) q?轮变换是对进入主循环?12位消息分l的16?2位字分别q行如下操作Q将A、B、C、D的副本a、b、c、d中的3个经F、G、H、Iq算后的l果与第4个相加,再加?2位字和一?2位字的加法常敎ͼq将所得之值@环左U若q位Q最后将所得结果加上a、b、c、d之一Qƈ回送至ABCDQ由此完成一ơ@环?/p>
所用的加法常数p样一张表T[i]来定义,其中i?…64QT[i]是i的正弦绝对g4294967296ơ方的整数部分,q样做是Z通过正u函数和幂函数来进一步消除变换中的线性性?/p>
当所?12位分l都q算完毕后,ABCD的联将被输ZؓMD5散列的结果。下面是一些MD5散列l果的例子:
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a 参考相应RFC文可以得到MD4、MD5法的详l描q和法的C源代码?/p>
3) SHA1 及其?nbsp; SHA1是由NIST NSA设计为同DSA一起用的Q访问http://www.itl.nist.gov/fipspubs可以得到它的详细规范--[/url]"FIPS PUB 180-1 SECURE HASH STANDARD"。它寚w度小?64的输入,产生长度?60bit的散列|因此抗穷?brute-force)性更好。SHA-1 设计时基于和MD4相同原理,q且模仿了该法。因为它?60bit的散列|因此它有5个参与运的32位寄存器字,消息分组和填充方式与MD5相同Q主循环也同h4轮,但每轮进?0ơ操作,非线性运、移位和加法q算也与MD5cMQ但非线性函数、加法常数和循环左移操作的设计有一些区别,可以参考上面提到的规范来了解这些细节。下面是一些SHA1散列l果的例子:
SHA1 ("abc") = a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d SHA1 ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1 其他一些知名的Hash法q有MD2、N-Hash、RIPE-MD、HAVAL{等。上面提到的q些都属?U?Hash法。还有另2cHash法Q一cd是基于对U分l算法的单向散列法Q典型的例子是基于DES的所谓Davies-Meyer法Q另外还有经IDEA改进的Davies-Meyer法Q它们两者目前都被认为是安全的算法。另一cLZ模运?LҎ的,也就是基于公开密钥法的,但因为其q算开销太大Q而缺乏很好的应用前景?/p>
没有通过分析和差分攻击考验的算法,大多都已l夭折在实验室里了,因此Q如果目前流行的Hash法能完全符合密码学意义上的单向性和抗冲H性,׃证了只有IDQ才是破坏Hashq算安全Ҏ的唯一Ҏ。ؓ了对抗弱抗冲H性,我们可能要穷举个数和散列值空间长度一样大的输入,卛_?^128?^160个不同的输入Q目前一台高个人电脑可能需?0^25q才能完成这一艰巨的工作,即是最高端的ƈ行系l,q也不是在几千年里的q得完的事。而因?生日d"有效的降低了需要穷丄I间Q将光低ؓ大约1.2*2^64?.2*2^80Q所以,强抗冲突性是军_Hash法安全性的关键?/p>
在NIST新的 Advanced Encryption Standard (AES)中,使用了长度ؓ128?92?56bit 的密钥,因此相应的设计了 SHA256、SHA384、SHA512Q它们将提供更好的安全性?/p>
Hash法在信息安全方面的应用主要体现在以下的3个方面:
1) 文g校验 我们比较熟悉的校验算法有奇偶校验和CRC校验Q这2U校验ƈ没有抗数据篡改的能力Q它们一定程度上能检ƈU正数据传输中的信道误码Q但却不能防止对数据的恶意破坏?/p>
MD5 Hash法?数字指纹"Ҏ,使它成ؓ目前应用最q泛的一U文件完整性校验和(Checksum)法Q不Unixpȝ有提供计md5 checksum的命令。它常被用在下面?U情况下Q?/p>
W一是文件传送后的校验,得到的目标文g计算 md5 checksumQ与源文件的md5 checksum 比对Q由两?md5 checksum 的一致性,可以从统计上保证2个文件的每一个码元也是完全相同的。这可以验文件传输过E中是否出现错误Q更重要的是可以保证文g在传输过E中未被恶意改。一个很典型的应用是ftp服务Q用户可以用来保证多ơ断点箋传,特别是从镜像站点下蝲的文件的正确性?/p>
更出色的解决Ҏ是所谓的代码{Q文件的提供者在提供文g的同Ӟ提供Ҏ件Hash值用自己的代码签名密钥进行数字签名的|及自q代码{证书。文件的接受者不仅能验证文g的完整性,q可以依据自己对证书{֏者和证书拥有者的信QE度Q决定是否接受该文g。浏览器在下载运行插件和java程序时Q用的是q样的模式?/p>
W二是用作保存二q制文gpȝ的数字指U,以便文件系l是否未l允许的被修攏V不系l管?pȝ安全软g都提供这一文gpȝ完整性评估的功能Q在pȝ初始安装完毕后,建立Ҏ件系l的基础校验和数据库Q因为散列校验和的长度很,它们可以方便的被存放在容量很的存储介质上。此后,可以定期或根据需要,再次计算文gpȝ的校验和Q一旦发C原来保存的值有不匹配,说明该文件已l被非法修改Q或者是被病毒感染,或者被木马E序替代。TripWire提供了一个此cd用的典型例子?/p>
更完的Ҏ是?MAC"?MAC" 是一个与Hash密切相关的名词,即信息鉴权码(Message Authority Code)。它是与密钥相关的Hash|必须拥有该密钥才能检验该Hash倹{文件系l的数字指纹也许会被保存在不可信ȝ介质上,只对拥有该密钥者提供可鉴别性。ƈ且在文g的数字指UҎ可能需要被修改的情况下Q只有密钥的拥有者可以计出新的散列|而企囄坏文件完整性者却不能得逞?/p>
2) 数字{ Hash 法也是C密码体系中的一个重要组成部分。由于非对称法的运速度较慢Q所以在数字{协议中,单向散列函数扮演了一个重要的角色?/p>
在这U签名协议中Q双方必M先协商好双方都支持的Hash函数和签名算法?/p>
{方先对该数据文gq行计算其散列|然后再对很短的散列值结?-如Md5?6个字节,SHA1?0字节Q用非对U算法进行数字签名操作。对方在验证{Ӟ也是先对该数据文件进行计其散列|然后再用非对U算法验证数字签名?/p>
?Hash |又称"数字摘要"q行数字{Q在l计上可以认ZҎ件本w进行数字签名是{效的。而且q样的协议还有其他的优点Q?/p>
首先Q数据文件本w可以同它的散列值分开保存Q签名验证也可以q数据文g本n的存在而进行?/p>
再者,有些情况下签名密钥可能与解密密钥是同一个,也就是说Q如果对一个数据文件签名,与对其进行非对称的解密操作是相同的操作,q是相当危险的,恶意的破坏者可能将一个试N你将其解密的文gQ充当一个要求你{的文件发送给你。因此,在对M数据文gq行数字{Ӟ只有对其HashD行签名才是安全的?/p>
3) 鉴权协议 如下的鉴权协议又被称?挑战--认证模式Q在传输信道是可被侦听,但不可被改的情况下Q这是一U简单而安全的Ҏ?/p>
需要鉴权的一方,向将被鉴权的一方发送随ZQ?#8220;挑战”Q,被鉴权方该随机串和自己的鉴权口令字一赯?Hash q算后,q还鉴权方,鉴权方将收到的Hashg在己端用该随Z和对方的鉴权口o字进?Hash q算的结果相比较Q?#8220;认证”Q,如相同,则可在统计上认ؓҎ拥有该口令字Q即通过鉴权?/p>
POP3协议中就有这一应用的典型例子:
S: +OK POP3 server ready <1896.697170952@dbc.mtview.ca.us> C: APOP mrose c4c9334bac560ecc979e58001b3e22fb S: +OK maildrop has 1 message (369 octets) 在上面的一DPOP3协议会话中,双方都共享的对称密钥Q鉴权口令字Q是tanstaafQ服务器发出的挑战是<1896.697170952@dbc.mtview.ca.us>Q客LҎ战的应答是MD5("<1896.697170952@dbc.mtview.ca.us>tanstaaf") = c4c9334bac560ecc979e58001b3e22fbQ这个正的应答使其通过了认证?/p>
散列法长期以来一直在计算机科学中大量应用Q随着C密码学的发展Q单向散列函数已l成Z息安全领域中一个重要的l构模块Q我们有理由深入研究其设计理论和应用Ҏ?/p>
]]>C++随机数生成方法(转蝲) http://www.shnenglu.com/softko/archive/2010/12/02/135228.htmleircQ eircQ Thu, 02 Dec 2010 00:42:00 GMT http://www.shnenglu.com/softko/archive/2010/12/02/135228.html http://www.shnenglu.com/softko/comments/135228.html http://www.shnenglu.com/softko/archive/2010/12/02/135228.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/135228.html http://www.shnenglu.com/softko/services/trackbacks/135228.html
原文 http://www.cnblogs.com/finallyliuyu/archive/2010/10/11/1848130.html
一、C++中不能用random()函数
==================================================================================
本文由青村֎创ƈ依GPL-V2及其后箋版本发放Q{载请注明出处且应包含本行声明?/p>
C++中常用rand()函数生成随机敎ͼ但严格意义上来讲生成的只是伪随机敎ͼpseudo-random integral
numberQ。生成随机数旉要我们指定一个种子,如果在程序内循环Q那么下一ơ生成随机数时调用上一ơ的l果作ؓU子。但如果分两ơ执行程序,那么?
于种子相同,生成?#8220;随机?#8221;也是相同的?/p>
在工E应用时Q我们一般将pȝ当前旉(Unix旉)作ؓU子Q这L成的随机数更接近于实际意义上的随机数。给一下例E如下:
#include <iostream> #include <ctime> #include <cstdlib> using namespace std;
int main() { double random(double,double); srand(unsigned(time(0))); for(int icnt = 0; icnt != 10; ++icnt) cout << "No." << icnt+1 << ": " << int(random(0,10))<< endl; return 0; }
double random(double start, double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); } /* q行l果 * No.1: 3 * No.2: 9 * No.3: 0 * No.4: 9 * No.5: 5 * No.6: 6 * No.7: 9 * No.8: 2 * No.9: 9 * No.10: 6 */ 利用q种Ҏ能不能得到完全意义上的随机数呢?g9有点多哦Q却没有1,4,7Q!我们来做一个概率实验,生成1000万个随机敎ͼ?-9q?0个数出现的频率是不是大致相同的。程序如下: #include <iostream> #include <ctime> #include <cstdlib> #include <iomanip> using namespace std;
int main() { double random(double,double); int a[10] = {0}; const int Gen_max = 10000000; srand(unsigned(time(0))); for(int icnt = 0; icnt != Gen_max; ++icnt) switch(int(random(0,10))) { case 0: a[0]++; break; case 1: a[1]++; break; case 2: a[2]++; break; case 3: a[3]++; break; case 4: a[4]++; break; case 5: a[5]++; break; case 6: a[6]++; break; case 7: a[7]++; break; case 8: a[8]++; break; case 9: a[9]++; break; default: cerr << "Error!" << endl; exit(-1); } for(int icnt = 0; icnt != 10; ++icnt)
cout << icnt << ": " << setw(6) <<
setiosflags(ios::fixed) << setprecision(2) <<
double(a[icnt])/Gen_max*100 << "%" << endl; return 0; }
double random(double start, double end) { return start+(end-start)*rand()/(RAND_MAX + 1.0); } /* q行l果 * 0: 10.01% * 1: 9.99% * 2: 9.99% * 3: 9.99% * 4: 9.98% * 5: 10.01% * 6: 10.02% * 7: 10.01% * 8: 10.01% * 9: 9.99% */ 可知用这U方法得到的随机数是满l计规律的?/p>
另:在Linux下利用GCC~译E序Q即使我执行?000000ơ运,是否random函数定义了inline函数g对程序没有Q何媄响,有理q信,GCC已经为我们做了优化。但是冥冥之中我又记得要做inline优化得加O3才行...
不行Q于是我们把循环ơ数改ؓ10亿次Q用time命o查看执行旉Q?br>chinsung@gentoo ~/workspace/test/Debug $ time ./test 0: 10.00% 1: 10.00% 2: 10.00% 3: 10.00% 4: 10.00% 5: 10.00% 6: 10.00% 7: 10.00% 8: 10.00% 9: 10.00%
real 2m7.768s user 2m4.405s sys 0m0.038schinsung@gentoo ~/workspace/test/Debug $ time ./test 0: 10.00% 1: 10.00% 2: 10.00% 3: 10.00% 4: 10.00% 5: 10.00% 6: 10.00% 7: 10.00% 8: 10.00% 9: 10.00%
real 2m7.269s user 2m4.077s sys 0m0.025s
前一ơؓq行inline优化的情形,后一ơؓ没有作inline优化的情形,两次l果相差不大Q甚臛_Ҏ标后者还要好一些,不知是何~由...
=================================================================================
random函数不是ANSI C标准Q不能在gcc,vc{编译器下编译通过?
可改用C++下的rand函数来实现?nbsp; 1、C++标准函数库提供一随机数生成器randQ返?QRAND_MAX之间均匀分布的伪随机整数?
RAND_MAX必须臛_?2767。rand()函数不接受参敎ͼ默认?为种子(卌v始|?
随机数生成器L以相同的U子开始,所以Ş成的伪随机数列也相同Q失M随机意义。(但这样便于程序调试) 2、C++中另一函数srandQ)Q可以指定不同的敎ͼ无符h数变元)为种子。但是如果种子相同,伪随机数列也相同。一个办法是让用戯入种子,但是仍然不理惟? 3?比较理想的是用变化的敎ͼ比如旉来作为随机数生成器的U子?time的值每时每刻都不同。所以种子不同,所以,产生的随机数也不同? // C++随机函数QVC programQ? #include <stdio.h> #include <iostream> #include <time.h> using namespace std; #define MAX 100 int main(int argc, char* argv[]) { srand( (unsigned)time( NULL ) );//srand()函数产生一个以当前旉开始的随机U子.应该攑֜for{@环语句前?不然要很长时间等? for (int i=0;i<10;i++) cout<<rand()%MAX<<endl;//MAX为最大|光机域?~MAX-1 return 0; } 二、rand()的用? rand()不需要参敎ͼ它会q回一个从0到最大随机数的Q意整敎ͼ最大随机数的大通常是固定的一个大整数?q样Q如果你要?~10?0个整敎ͼ可以表达为: int N = rand() % 11; q样QN的值就是一?~10的随机数Q如果要产生1~10Q则是这P int N = 1 + rand() % 10; ȝ来说Q可以表CZؓQ? a + rand() % n
其中的a是v始|n是整数的范围? a + rand() % (b-a+1)
pC a~b之间的一个随机数若要0~1的小敎ͼ则可以先取得0~10的整敎ͼ然后均除?0卛_得到随机到十分位?0个随机小敎ͼ若要得到随机到百
分位的随机小敎ͼ则需要先得到0~100?0个整敎ͼ然后均除?00Q其它情况依此类推? 通常rand()产生的随机数在每ơ运行的时候都是与上一ơ相同的Q这是有意这栯计的Q是Z便于E序的调试。若要生每ơ不同的随机敎ͼ可以使用srand( seed )函数q行随机化,随着seed的不同,p够生不同的随机数? 如大家所_q可以包含time.h头文Ӟ然后使用srand(time(0))来用当前时间随机数发生器随机化,q样可以保证每两次q行时可以得C同的随机数序?只要两次q行的间隔超q?U??/p>
]]> trie?-详解 http://www.shnenglu.com/softko/archive/2010/11/26/134701.htmleircQ eircQ Fri, 26 Nov 2010 01:48:00 GMT http://www.shnenglu.com/softko/archive/2010/11/26/134701.html http://www.shnenglu.com/softko/comments/134701.html http://www.shnenglu.com/softko/archive/2010/11/26/134701.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/134701.html http://www.shnenglu.com/softko/services/trackbacks/134701.html 文章作者: yx_th000 文章来源Q?/span>C herish_yimi ( http://www.cnblogs.com/cherish_yimi/ ) 转蝲h明,谢谢合作?br> 关键词:trie trie?数据l构
前几天学习了q查集和trie树,q里ȝ一下trie?br> 本文讨论一|单的trie树,Z英文26个字母组成的字符Ԍ讨论插入字符丌Ӏ判断前~是否存在、查扑֭W串{基本操作;至于trie树的删除单个节点实在是少见,故在此不做详解?/span>
l Trie 原理
Trie 的核心思想是空间换旉。利用字W串的公共前~来降低查询时间的开销以达到提高效率的目的?/span>
l Trie 性质
好多trie的根节点不包含Q何字W信息,我所习惯的trie根节点却是包含信息的Q而且认ؓq样也方便,下面说一下它的性质 (Z本文所讨论的简单trie?
1. 字符的种数决定每个节点的出度Q即branch数组(I间换时间思想)
2. branch 数组的下标代表字W相对于a的相对位|?/span>
3. 采用标记的方法确定是否ؓ字符丌Ӏ?/span>
4. 插入、查扄复杂度均为O(len),len为字W串长度
l Trie 的示意图
如图所C,该trie树存有abc、d、da、dda四个字符Ԍ如果是字W串会在节点的尾部进行标记。没有后l字W的branch分支指向NULL l Trie Trie 的优点D?/span>
已知n个由写字母构成的^均长度ؓ10的单?判断其中是否存在某个串ؓ另一个串的前~子串。下面对?U方法:
1. 最Ҏ惛_的:即从字符串集中从头往后搜Q看每个字符串是否ؓ字符串集中某个字W串的前~Q复杂度为O(n^2)?/span>
2. 使用hashQ我们用hash存下所有字W串的所有的前缀子串。徏立存有子串hash的复杂度为O(n*len)。查询的复杂度ؓO(n)* O(1)= O(n)?/span>
3. ?
用trieQ因为当查询如字W串abc是否为某个字W串的前~Ӟ昄以b,c,d....{不是以a开头的字符串就不用查找了。所以徏立trie的复?
度ؓO(n*len)Q而徏?查询在trie中是可以同时执行的,建立的过E也可以成为查询的q程Qhash׃能实现这个功能。所以ȝ复杂度ؓ
O(n*len)Q实际查询的复杂度只是O(len)?br>
解释一?
hashZ么不能将建立与查询同时执行,例如有串Q?11Q?11456输入Q如果要同时执行建立与查询,q程是查询911Q没有,然后存入9?
91?11Q查?11456Q没有然后存?114?1145?11456Q而程序没有记忆功能,q不知道911在输入数据中出现q。所以用
hash必须先存入所有子Ԍ然后for循环查询?/span>
而trie树便?
以,存入911后,已经记录911为出现的字符Ԍ在存?11456的过E中p发现而输出答案;倒过来亦可以Q先存入911456Q在存入911Ӟ
当指针指向最后一?ӞE序会发现这?已经存在Q说?11必定是某个字W串的前~Q该思想是我在做pku上的3630中发现的Q详见本文配套的“?
门练?#8221;?/span>
l Trie 的简单实 ?插入、查 ?
Code 1 2 #include < iostream > 3 using namespace std; 4 5 const int branchNum = 26 ; // 声明帔R 6 int i; 7 8 struct Trie_node 9 { 10 bool isStr; // 记录此处是否构成一个串?/span>11 Trie_node * next[branchNum]; // 指向各个子树的指?下标0-25代表26字符 12 Trie_node():isStr( false ) 13 { 14 memset(next,NULL,sizeof (next)); 15 }16 } ; 17 18 class Trie 19 { 20 public : 21 Trie();22 void insert( const char * word); 23 bool search( char * word); 24 void deleteTrie(Trie_node * root); 25 private : 26 Trie_node* root; 27 }; 28 29 Trie::Trie()30 { 31 root = new Trie_node(); 32 }33 34 void Trie::insert( const char * word) 35 { 36 Trie_node * location = root; 37 while ( * word) 38 { 39 if (location -> next[ * word - ' a ' ] == NULL) // 不存在则建立 40 { 41 Trie_node * tmp = new Trie_node(); 42 location-> next[ * word - ' a ' ] = tmp; 43 } 44 location = location -> next[ * word - ' a ' ]; // 每插入一步,相当于有一个新串经q,指针要向下移?/span>45 word ++ ; 46 } 47 location-> isStr = true ; // 到达N,标记一个串 48 } 49 50 bool Trie::search( char * word) 51 { 52 Trie_node * location = root; 53 while ( * word && location) 54 { 55 location = location -> next[ * word - ' a ' ]; 56 word++ ; 57 }58 return (location != NULL && location -> isStr); 59 }60 61 void Trie::deleteTrie(Trie_node * root) 62 { 63 for (i = 0 ; i < branchNum; i ++ ) 64 { 65 if (root -> next[i] != NULL) 66 { 67 deleteTrie(root-> next[i]); 68 }69 }70 delete root;71 }72 73 void main() // 单测?/span>74 { 75 Trie t;76 t.insert(" a " ); 77 t.insert(" abandon " ); 78 char * c = " abandoned " ; 79 t.insert(c);80 t.insert(" abashed " ); 81 if (t.search( " abashed " )) 82 printf(" true\n " ); 83 }
]]>常用函数的源码实?/title> http://www.shnenglu.com/softko/archive/2010/08/23/124416.htmleircQ eircQ Mon, 23 Aug 2010 06:42:00 GMT http://www.shnenglu.com/softko/archive/2010/08/23/124416.html http://www.shnenglu.com/softko/comments/124416.html http://www.shnenglu.com/softko/archive/2010/08/23/124416.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/124416.html http://www.shnenglu.com/softko/services/trackbacks/124416.html ;***************************************************************************************************************
; strlen returns the length of a null-terminated string in
bytes, not including the null byte itself.
; Algorithm:
; int strlen (const char * str)
; {
; int length = 0;
;
; while( *str++ )
; ++length;
;
; return( length );
; }
;***************************************************************************************************************
; memcpy() copies a source memory buffer to a destination
buffer.
; Overlapping buffers are not treated specially, so
propogation may occur.
; Algorithm:
; void * memcpy(void * dst, void * src, size_t count)
; {
; void * ret = dst;
; /*
; * copy from lower addresses to higher addresses
; */
; while (count--)
; *dst++ = *src++;
;
; return(ret);
; }
;***************************************************************************************************************
; memmove() copies a source memory buffer to a destination
memory buffer.
; This routine recognize overlapping buffers to avoid
propogation.
; For cases where propogation is not a problem, memcpy() can
be used.
; Algorithm:
; void * memmove(void * dst, void * src, size_t count)
; {
; void * ret = dst;
; if (dst <= src || dst >= (src + count)) {
; /*
; * Non-Overlapping Buffers
; * copy from lower addresses to higher
addresses
; */
; while (count--)
; *dst++ = *src++;
; }
; else {
; /*
; * Overlapping Buffers
; * copy from higher addresses to lower
addresses
; */
; dst += count - 1;
; src += count - 1;
;
; while (count--)
; *dst-- = *src--;
; }
;
; return(ret);
; }
;***************************************************************************************************************
int strcmp(const char *str1,const char *str2)
{
while((*str1==*str2)&&(*str1))
{
str1++;
str2++;
}
if((*str1==*str2)&&(!*str1)) //Same strings
return 0;
else if((*str1)&&(!*str2)) //Same but str1 longer
return -1;
else if((*str2)&&(!*str1)) //Same but str2 longer
return 1;
else
return((*str1>*str2)?-1:1);
}
;***************************************************************************************************************
char *strstr1(const char *str1, const char *str2)
{
char *cp = (char *)str1; //type transfer
char *s1, *s2;
if(!str2)
return (char *)str1;
while (cp)
{
s1 = cp;
s2 = (char *)str2;
while( !s1 && !s2 && !(*s1-*s2))
{
s1++, s2++;
}
if(!s2)
return cp;
else
cp++;
}
return NULL;
}
;***************************************************************************************************************
*char *_itoa, *_ltoa, *_ultoa(val, buf, radix) - convert binary int
to ASCII string
static void __cdecl xtoa (unsigned long val, char *buf, unsigned
radix, int is_neg )
{
char *p; /* pointer to traverse string */
char *firstdig; /* pointer to first digit */
char temp; /* temp char */
unsigned digval; /* value of digit */
p = buf;
if (is_neg) {
/* negative, so output '-' and negate */
*p++ = '-';
val = (unsigned long)(-(long)val);
}
firstdig = p; /* save pointer to first digit */
do {
digval = (unsigned) (val % radix);
val /= radix; /* get next digit */
/* convert to ascii and store */
if (digval > 9)
*p++ = (char) (digval - 10 + 'a'); /* a letter */
else
*p++ = (char) (digval + '0'); /* a digit */
} while (val > 0);
/* We now have the digit of the number in the buffer, but in
reverse
order. Thus we reverse them now. */
*p-- = '\0'; /* terminate string; p points to last
digit */
do {
temp = *p;
*p = *firstdig;
*firstdig = temp; /* swap *p and *firstdig */
--p;
++firstdig; /* advance to next two digits */
} while (firstdig < p); /* repeat until halfway */
}
char * __cdecl _itoa ( int val, char *buf, int radix )
{
if (radix == 10 && val < 0)
xtoa((unsigned long)val, buf, radix, 1);
else
xtoa((unsigned long)(unsigned int)val, buf, radix, 0);
return buf;
}
char * __cdecl _ltoa ( long val, char *buf, int radix )
{
xtoa((unsigned long)val, buf, radix, (radix == 10 &&
val < 0));
return buf;
}
;***************************************************************************************************************
*long atol(char *nptr) - Convert string to long. Overflow is not
detected.
long __cdecl _tstol(const _TCHAR *nptr )
{
int c; /* current char */
long total; /* current total */
int sign; /* if '-', then negative, otherwise
positive */
while ( _istspace((int)(_TUCHAR)*nptr) )
++nptr; /* skip whitespace */
c = (int)(_TUCHAR)*nptr++;
sign = c; /* save sign indication */
if (c == _T('-') || c == _T('+'))
c = (int)(_TUCHAR)*nptr++; /* skip sign */
total = 0;
while ( (c = _tchartodigit(c)) != -1 ) {
total = 10 * total + c; /* accumulate digit */
c = (_TUCHAR)*nptr++; /* get next char */
}
if (sign == '-')
return -total;
else
return total; /* return result, negated if necessary
*/
}
int __cdecl _tstoi( const _TCHAR *nptr )
{
return (int)_tstol(nptr);
}
;***************************************************************************************************************
;performs a byteswap on an unsigned integer.
unsigned short __cdecl _byteswap_ushort(unsigned short i)
{
unsigned short j;
j = (i << 8) ;
j += (i >> 8) ;
return j;
}
unsigned long __cdecl _byteswap_ulong(unsigned long i)
{
unsigned int j;
j = (i << 24);
j += (i << 8) & 0x00FF0000;
j += (i >> 8) & 0x0000FF00;
j += (i >> 24);
return j;
}
;***************************************************************************************************************
*char *bsearch() - do a binary search on an array
*Entry:
* const char *key - key to search for const char *base -
base of sorted array to search unsigned int num - number of *elements
in array unsigned int width - number of bytes per element int
(*compare)() - pointer to function that compares two
*array elements, returning neg when #1 < #2, pos when #1 > #2,
and 0 when they are equal. Function is passed pointers to two
*array elements.
*Exit:
* if key is found: returns pointer to occurrence of key in
array
* if key is not found:returns NULL
void * __cdecl bsearch ( REG4 const void *key, const void *base,
size_t num, size_t width, int (__cdecl *compare)(const void *, const
void *) )
{
REG1 char *lo = (char *)base;
REG2 char *hi = (char *)base + (num - 1) * width;
REG3 char *mid;
size_t half;
int result;
while (lo <= hi)
if (half = num / 2)
{
mid = lo + (num & 1 ? half : (half - 1))
* width;
if (!(result = (*compare)(key,mid)))
return(mid);
else if (result < 0)
{
hi = mid - width;
num = num & 1 ? half : half-1;
}
else {
lo = mid + width;
num = half;
}
}
else if (num)
return((*compare)(key,lo) ? NULL : lo);
else
break;
return(NULL);
}
;***************************************************************************************************************
void __cdecl _tmakepath (register _TSCHAR *path, const _TSCHAR
*drive, const _TSCHAR *dir,
const _TSCHAR *fname, const _TSCHAR *ext )
{
register const _TSCHAR *p;
/* copy drive */
if (drive && *drive) {
*path++ = *drive;
*path++ = _T(':');
}
/* copy dir */
if ((p = dir) && *p) {
do {
*path++ = *p++;
}while (*p);
if (*(p-1) != _T('/') && *(p-1) != _T('\\'))
{
*path++ = _T('\\');
}
}
/* copy fname */
if (p = fname) {
while (*p) {
*path++ = *p++;
}
}
/* copy ext, including 0-terminator - check to see if a '.'
needs to be inserted. */
if (p = ext) {
if (*p && *p != _T('.')) {
*path++ = _T('.');
}
while (*path++ = *p++)
;
}
else {
/* better add the 0-terminator */
*path = _T('\0');
}
}
]]> 两单向链表相?/title> http://www.shnenglu.com/softko/archive/2010/08/18/123811.htmleircQ eircQ Wed, 18 Aug 2010 03:26:00 GMT http://www.shnenglu.com/softko/archive/2010/08/18/123811.html http://www.shnenglu.com/softko/comments/123811.html http://www.shnenglu.com/softko/archive/2010/08/18/123811.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/123811.html http://www.shnenglu.com/softko/services/trackbacks/123811.html 2. /* 功能Q求两个单链表是否相交和交点*/ 3. /* 转蝲自CSDN博客 * / 4. /* 日期Q?010/03/29 */ 5. /***********************************/ 6. 7. 8. Node* find(Node* head1,Node* head2) 9. { 10. Node *p1=head1,*p2=head2; 11. int m=0,n=0; 12. while(p1)//O(len1) 13. { 14. p1=p1->next; 15. m++; 16. } 17. while(p2)//O(len2) 18. { 19. p2=p2->next; 20. n++; 21. } 22. p1=head1; 23. p2=head2; 24. 25. if(m>n) 26. { 27. for(i=0;i<m-n;i++) 28. p1=p1->next; 29. } 30. else 31. { 32. for(i=0;i<n-m;i++) 33. p2=p2->next; 34. }//O(abs(len1-len2)) 35. while(p1!=p2) 36. { 37. p1=p1->next; 38. p2=p2->next; 39. }//O(min(len1,len2)) 40. return p1; 41. }
]]> c与汇~,以及嵌入式工E师应注意的问题 http://www.shnenglu.com/softko/archive/2010/07/25/121229.htmleircQ eircQ Sun, 25 Jul 2010 03:43:00 GMT http://www.shnenglu.com/softko/archive/2010/07/25/121229.html http://www.shnenglu.com/softko/comments/121229.html http://www.shnenglu.com/softko/archive/2010/07/25/121229.html#Feedback 0 http://www.shnenglu.com/softko/comments/commentRss/121229.html http://www.shnenglu.com/softko/services/trackbacks/121229.html c与汇~,以及嵌入式工E师应注意的问题
人生哲理与经?/a>
2007-07-25 13:31:04
阅读41
评论
字号Q?span class="ul sep fc04">?/span>?/span>?/span>
汇编和c同样重要Q相互配合,~Z不可Q?
汇编的重要性:
?帮助你从Ҏ上彻底和完全了解芯片的结构和性能Q以及工作原理,如何使用? ?在小的芯片上实现的pȝ? ?pȝ的调试。尽你使用了高U语aQ在调试中可以帮助你了解C代码的性能和特点,甚至扑ֈ使用开发^台本w的BUG? ?~写时序要求严格的代码,实现一些高U语a不易实现的功能?
出版的AVR128的书里面Q第五章中主使用C作ؓpȝ开发设计语aQ这是因为M128的速度高,内部?K的RAMQ?28KFLASHQ?
适合于实现比较高U的应用Q所以采用C语言作ؓpȝ开发的设计语言。但作ؓ开发工E师来讲Q熟悉M128的结构和应用原理Q基本掌握它的汇~语a是必要的
基础?
从目前的技术和应用发展来看Q对g工程师的要求来高。以我的观点Q作为单片机和嵌入式pȝ开发真正的高手Q应具备以下几个斚w的综合能力:
?g。模拟、数字电路的雄厚基础Q了解跟t现在市Z的各U元器g的应用和发展Q能够进行可靠、完善的电\设计以及PCB的设计? ?
软g。不仅需要精通汇~语aQ也要精通C语言Q要有好的单片机pȝE序设计理念和能力,学校中学的那些分支结构、@环结构等基本原理q远不够Q要有基本的
数据l构的知识。否则你如何设计实现USB HOST读U盘的接口Q如何实现嵌入式WEBpȝQ以及如何用真正了解和使用RTOSQ? ?具备计算机网l和数字通信的基知识Q从Ҏ上熟悉和了解各种协议的构造和实现Q如QUART、RS232、SPI、I2C、USB、IEEE802、TCP/IP{? ?计算机应用的高手? ?熟练阅读英文资料? ?热爱和喜Ƣ电子技术,具备刻苦_、踏t实实,不弄虚作假,不Qw。多动手Q勤实践。有强烈的专业和ȝ_。最后一条最重要Q?
]]>
þþƷƷƷ |
þþþAV |
þþþһƷɫav |
ŷƷһþ |
Ʒһþþ |
99þerֻоƷ18 |
94þùƷ |
þۺϾƷһ |
aëƬþѲ |
þAV뾫Ʒɫҹ鶹 |
þ91Ʒþ91ۺ |
91ɫۺϾþѷ |
þۺ϶㼤þ |
þ99ù龫Ʒ66 |
þþþùһ
|
ƷþþþþĻ
|
žžþþƷ |
þAV˳ |
þþþùƷ |
˾þۺ |
99þþƷһ |
þùҹƷһ |
þרƷ |
þùƷһƷ |
˾ƷۺϾþþ |
þþƷ |
Ʒ99þþþƷ
|
þþþó˾ƷĻ
|
ٸۺϾþĻ |
ξþ99ƷþþþþС˵
|
þ99һ |
þþƷ |
þþþavר
|
þþŷղa |
þ㽶߿ۿ |
ݺɫþۺͼƬ |
þ99Ʒ |
þþƷ2020 |
þ |
һһþþƷۺ |
ɫ͵͵þһ |