??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品久久久久蜜芽,97超级碰碰碰碰久久久久,久久久久成人精品无码中文字幕 http://www.shnenglu.com/softko/category/14124.html淡薄名利,修nL?/description>zh-cnWed, 22 Jun 2011 09:08:07 GMTWed, 22 Jun 2011 09:08:07 GMT60各种排序法介绍http://www.shnenglu.com/softko/archive/2011/06/17/148828.htmleircQeircQFri, 17 Jun 2011 00:09:00 GMThttp://www.shnenglu.com/softko/archive/2011/06/17/148828.htmlhttp://www.shnenglu.com/softko/comments/148828.htmlhttp://www.shnenglu.com/softko/archive/2011/06/17/148828.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/148828.htmlhttp://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?

eircQ 2011-06-17 08:09 发表评论
]]>
Hash 法及其应用(?http://www.shnenglu.com/softko/archive/2010/12/02/135309.htmleircQeircQThu, 02 Dec 2010 15:08:00 GMThttp://www.shnenglu.com/softko/archive/2010/12/02/135309.htmlhttp://www.shnenglu.com/softko/comments/135309.htmlhttp://www.shnenglu.com/softko/archive/2010/12/02/135309.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/135309.htmlhttp://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>



eircQ 2010-12-02 23:08 发表评论
]]>
C++随机数生成方法(转蝲)http://www.shnenglu.com/softko/archive/2010/12/02/135228.htmleircQeircQThu, 02 Dec 2010 00:42:00 GMThttp://www.shnenglu.com/softko/archive/2010/12/02/135228.htmlhttp://www.shnenglu.com/softko/comments/135228.htmlhttp://www.shnenglu.com/softko/archive/2010/12/02/135228.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/135228.htmlhttp://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.038s
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.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>



eircQ 2010-12-02 08:42 发表评论
]]>
trie?-详解http://www.shnenglu.com/softko/archive/2010/11/26/134701.htmleircQeircQFri, 26 Nov 2010 01:48:00 GMThttp://www.shnenglu.com/softko/archive/2010/11/26/134701.htmlhttp://www.shnenglu.com/softko/comments/134701.htmlhttp://www.shnenglu.com/softko/archive/2010/11/26/134701.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/134701.htmlhttp://www.shnenglu.com/softko/services/trackbacks/134701.html文章作者:yx_th000 文章来源Q?/span>Cherish_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的简单实?插入、查?


 1
 2#include <iostream>
 3using namespace std;
 4
 5const int branchNum = 26//声明帔R 
 6int i;
 7
 8struct 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
18class Trie
19{
20public:
21    Trie();
22    void insert(const char* word);
23    bool search(char* word); 
24    void deleteTrie(Trie_node *root);
25private:
26    Trie_node* root;
27}
;
28
29Trie::Trie()
30{
31    root = new Trie_node();
32}

33
34void 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
50bool 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
61void 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
73void 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}



eircQ 2010-11-26 09:48 发表评论
]]>
常用函数的源码实?/title><link>http://www.shnenglu.com/softko/archive/2010/08/23/124416.html</link><dc:creator>eircQ</dc:creator><author>eircQ</author><pubDate>Mon, 23 Aug 2010 06:42:00 GMT</pubDate><guid>http://www.shnenglu.com/softko/archive/2010/08/23/124416.html</guid><wfw:comment>http://www.shnenglu.com/softko/comments/124416.html</wfw:comment><comments>http://www.shnenglu.com/softko/archive/2010/08/23/124416.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/softko/comments/commentRss/124416.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/softko/services/trackbacks/124416.html</trackback:ping><description><![CDATA[<p>;*************************************************************************************************************** <br>;       strlen returns the length of a null-terminated string in bytes, not including the null byte itself. <br>;       Algorithm: <br>;       int strlen (const char * str) <br>;       { <br>;           int length = 0; <br>; <br>;           while( *str++ ) <br>;                   ++length; <br>; <br>;           return( length ); <br>;       } <br> <br>;*************************************************************************************************************** <br>;       memcpy() copies a source memory buffer to a destination buffer. <br>;       Overlapping buffers are not treated specially, so propogation may occur. <br>;       Algorithm: <br>;       void * memcpy(void * dst, void * src, size_t count) <br>;       { <br>;               void * ret = dst; <br>;               /* <br>;                * copy from lower addresses to higher addresses <br>;                */ <br>;               while (count--) <br>;                       *dst++ = *src++; <br>; <br>;               return(ret); <br>;       } <br> <br>;*************************************************************************************************************** <br>;       memmove() copies a source memory buffer to a destination memory buffer. <br>;       This routine recognize overlapping buffers to avoid propogation. <br>;       For cases where propogation is not a problem, memcpy() can be used. <br>;       Algorithm: <br>;       void * memmove(void * dst, void * src, size_t count) <br>;       { <br>;               void * ret = dst; <br>;               if (dst <= src || dst >= (src + count)) { <br>;                       /* <br>;                        * Non-Overlapping Buffers <br>;                        * copy from lower addresses to higher addresses <br>;                        */ <br>;                       while (count--) <br>;                               *dst++ = *src++; <br>;                       } <br>;               else { <br>;                       /* <br>;                        * Overlapping Buffers <br>;                        * copy from higher addresses to lower addresses <br>;                        */ <br>;                       dst += count - 1; <br>;                       src += count - 1; <br>; <br>;                       while (count--) <br>;                               *dst-- = *src--; <br>;                       } <br>; <br>;               return(ret); <br>;       } <br> <br>;*************************************************************************************************************** <br>int strcmp(const char *str1,const char *str2) <br>{ <br>while((*str1==*str2)&&(*str1)) <br>{ <br>str1++; <br>str2++; <br>} <br>if((*str1==*str2)&&(!*str1)) //Same strings <br>return 0; <br>else if((*str1)&&(!*str2))  //Same but str1 longer <br>return -1; <br>else if((*str2)&&(!*str1)) //Same but str2 longer <br>return 1; <br>else <br>return((*str1>*str2)?-1:1); <br>} <br> <br>;*************************************************************************************************************** <br>char *strstr1(const char *str1, const char *str2) <br>{ <br>     char *cp = (char *)str1;  //type transfer <br>     char *s1, *s2; <br>     if(!str2)  <br>      return (char *)str1; <br>     while (cp) <br>     { <br>      s1 = cp; <br>      s2 = (char *)str2; <br>      while( !s1 && !s2 && !(*s1-*s2)) <br>      { <br>       s1++, s2++; <br>      } <br>      if(!s2)  <br>       return cp; <br>      else <br>       cp++; <br>     } <br>     return NULL; <br>} <br> <br>;*************************************************************************************************************** <br>*char *_itoa, *_ltoa, *_ultoa(val, buf, radix) - convert binary int to ASCII string <br>static void __cdecl xtoa (unsigned long val, char *buf, unsigned radix, int is_neg ) <br>{ <br>        char *p;                /* pointer to traverse string */ <br>        char *firstdig;         /* pointer to first digit */ <br>        char temp;              /* temp char */ <br>        unsigned digval;        /* value of digit */ </p> <p>        p = buf;</p> <p>        if (is_neg) { <br>            /* negative, so output '-' and negate */ <br>            *p++ = '-'; <br>            val = (unsigned long)(-(long)val); <br>        } </p> <p>        firstdig = p;           /* save pointer to first digit */</p> <p>        do { <br>            digval = (unsigned) (val % radix); <br>            val /= radix;       /* get next digit */ </p> <p>            /* convert to ascii and store */ <br>            if (digval > 9) <br>                *p++ = (char) (digval - 10 + 'a');  /* a letter */ <br>            else <br>                *p++ = (char) (digval + '0');       /* a digit */ <br>        } while (val > 0); </p> <p>        /* We now have the digit of the number in the buffer, but in reverse <br>           order.  Thus we reverse them now. */ </p> <p>        *p-- = '\0';            /* terminate string; p points to last digit */</p> <p>        do { <br>            temp = *p; <br>            *p = *firstdig; <br>            *firstdig = temp;   /* swap *p and *firstdig */ <br>            --p; <br>            ++firstdig;         /* advance to next two digits */ <br>        } while (firstdig < p); /* repeat until halfway */ <br>} <br>char * __cdecl _itoa ( int val, char *buf, int radix ) <br>{ <br>        if (radix == 10 && val < 0) <br>            xtoa((unsigned long)val, buf, radix, 1); <br>        else <br>            xtoa((unsigned long)(unsigned int)val, buf, radix, 0); <br>        return buf; <br>} <br>char * __cdecl _ltoa ( long val, char *buf, int radix ) <br>{ <br>        xtoa((unsigned long)val, buf, radix, (radix == 10 && val < 0)); <br>        return buf; <br>} <br> <br>;*************************************************************************************************************** <br>*long atol(char *nptr) - Convert string to long. Overflow is not detected. <br>long __cdecl _tstol(const _TCHAR *nptr ) <br>{ <br>        int c;              /* current char */ <br>        long total;         /* current total */ <br>        int sign;           /* if '-', then negative, otherwise positive */ <br>        while ( _istspace((int)(_TUCHAR)*nptr) ) <br>                 ++nptr;   /* skip whitespace */ </p> <p>        c = (int)(_TUCHAR)*nptr++; <br>        sign = c;           /* save sign indication */ <br>        if (c == _T('-') || c == _T('+')) <br>            c = (int)(_TUCHAR)*nptr++;    /* skip sign */ </p> <p>        total = 0;</p> <p>        while ( (c = _tchartodigit(c)) != -1 ) { <br>            total = 10 * total + c;     /* accumulate digit */ <br>            c = (_TUCHAR)*nptr++;    /* get next char */ <br>        } </p> <p>        if (sign == '-') <br>            return -total; <br>        else <br>            return total;   /* return result, negated if necessary */ <br>} <br>int __cdecl _tstoi( const _TCHAR *nptr ) <br>{ <br>        return (int)_tstol(nptr); <br>} <br> <br>;*************************************************************************************************************** <br>;performs a byteswap on an unsigned integer. <br>unsigned short __cdecl _byteswap_ushort(unsigned short i) <br>{ <br>    unsigned short j; <br>    j =  (i << 8) ; <br>    j += (i >> 8) ; <br>    return j; <br>} <br>unsigned long __cdecl _byteswap_ulong(unsigned long i) <br>{ <br>    unsigned int j; <br>    j =  (i << 24); <br>    j += (i <<  8) & 0x00FF0000; <br>    j += (i >>  8) & 0x0000FF00; <br>    j += (i >> 24); <br>    return j; <br>} <br> <br>;*************************************************************************************************************** <br>*char *bsearch() - do a binary search on an array <br>*Entry: <br>*       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 <br>*array elements, returning neg when #1 < #2, pos when #1 > #2, and 0 when they are equal. Function is passed pointers to two <br>*array elements. <br>*Exit: <br>*       if key is found: returns pointer to occurrence of key in array <br>*       if key is not found:returns NULL <br> <br>void * __cdecl bsearch ( REG4 const void *key, const void *base, size_t num, size_t width, int (__cdecl *compare)(const void *, const void *)   ) <br>{ <br>        REG1 char *lo = (char *)base; <br>        REG2 char *hi = (char *)base + (num - 1) * width; <br>        REG3 char *mid; <br>        size_t half; <br>        int result; </p> <p>        while (lo <= hi) <br>                if (half = num / 2) <br>                { <br>                        mid = lo + (num & 1 ? half : (half - 1)) * width; <br>                        if (!(result = (*compare)(key,mid))) <br>                                return(mid); <br>                        else if (result < 0) <br>                        { <br>                                hi = mid - width; <br>                                num = num & 1 ? half : half-1; <br>                        } <br>                        else    { <br>                                lo = mid + width; <br>                                num = half; <br>                        } <br>                } <br>                else if (num) <br>                        return((*compare)(key,lo) ? NULL : lo); <br>                else <br>                        break; </p> <p>        return(NULL); <br>} <br> <br>;*************************************************************************************************************** <br>void __cdecl _tmakepath (register _TSCHAR *path, const _TSCHAR *drive, const _TSCHAR *dir, <br>const _TSCHAR *fname, const _TSCHAR *ext  ) <br>{ <br>     register const _TSCHAR *p; <br>     /* copy drive */ <br>     if (drive && *drive) { <br>                *path++ = *drive; <br>                *path++ = _T(':'); <br>        } </p> <p>        /* copy dir */ <br>        if ((p = dir) && *p) { <br>                do { <br>                        *path++ = *p++; <br>                }while (*p); <br>                if (*(p-1) != _T('/') && *(p-1) != _T('\\')) { <br>                        *path++ = _T('\\'); <br>                } <br>        } </p> <p>        /* copy fname */ <br>        if (p = fname) { <br>                while (*p) { <br>                        *path++ = *p++; <br>                } <br>        } </p> <p>        /* copy ext, including 0-terminator - check to see if a '.' needs to be inserted. */ <br>        if (p = ext) { <br>                if (*p && *p != _T('.')) { <br>                        *path++ = _T('.'); <br>                } <br>                while (*path++ = *p++) <br>                        ; <br>        } <br>        else { <br>                /* better add the 0-terminator */ <br>                *path = _T('\0'); <br>        } <br>} </p> <br><img src ="http://www.shnenglu.com/softko/aggbug/124416.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/softko/" target="_blank">eircQ</a> 2010-08-23 14:42 <a href="http://www.shnenglu.com/softko/archive/2010/08/23/124416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>两单向链表相?/title><link>http://www.shnenglu.com/softko/archive/2010/08/18/123811.html</link><dc:creator>eircQ</dc:creator><author>eircQ</author><pubDate>Wed, 18 Aug 2010 03:26:00 GMT</pubDate><guid>http://www.shnenglu.com/softko/archive/2010/08/18/123811.html</guid><wfw:comment>http://www.shnenglu.com/softko/comments/123811.html</wfw:comment><comments>http://www.shnenglu.com/softko/archive/2010/08/18/123811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/softko/comments/commentRss/123811.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/softko/services/trackbacks/123811.html</trackback:ping><description><![CDATA[   1. /***********************************/  <br>   2. /* 功能Q求两个单链表是否相交和交点*/  <br>   3. /* 转蝲自CSDN博客                  * /  <br>   4. /* 日期Q?010/03/29                */  <br>   5. /***********************************/  <br>   6.   <br>   7.   <br>   8. Node* find(Node* head1,Node* head2)     <br>   9. {     <br>  10.      Node *p1=head1,*p2=head2;     <br>  11.     int m=0,n=0;     <br>  12.     while(p1)//O(len1)     <br>  13.      {<br>  14.          p1=p1->next;     <br>  15.          m++;<br>  16.      }<br>  17.     while(p2)//O(len2)<br>  18.      {<br>  19.          p2=p2->next;     <br>  20.          n++;     <br>  21.      }<br>  22.      p1=head1;<br>  23.      p2=head2;<br>  24.           <br>  25.     if(m>n)<br>  26.      {     <br>  27.         for(i=0;i<m-n;i++)     <br>  28.              p1=p1->next;     <br>  29.      }<br>  30.     else<br>  31.      {<br>  32.         for(i=0;i<n-m;i++) <br>  33.                p2=p2->next;<br>  34.      }//O(abs(len1-len2))<br>  35.     while(p1!=p2)<br>  36.      {<br>  37.          p1=p1->next;<br>  38.          p2=p2->next;     <br>  39.      }//O(min(len1,len2))     <br>  40.     return p1;<br>  41. } <br><img src ="http://www.shnenglu.com/softko/aggbug/123811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/softko/" target="_blank">eircQ</a> 2010-08-18 11:26 <a href="http://www.shnenglu.com/softko/archive/2010/08/18/123811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c与汇~,以及嵌入式工E师应注意的问题http://www.shnenglu.com/softko/archive/2010/07/25/121229.htmleircQeircQSun, 25 Jul 2010 03:43:00 GMThttp://www.shnenglu.com/softko/archive/2010/07/25/121229.htmlhttp://www.shnenglu.com/softko/comments/121229.htmlhttp://www.shnenglu.com/softko/archive/2010/07/25/121229.html#Feedback0http://www.shnenglu.com/softko/comments/commentRss/121229.htmlhttp://www.shnenglu.com/softko/services/trackbacks/121229.htmlc与汇~,以及嵌入式工E师应注意的问题

人生哲理与经?/a> 2007-07-25 13:31:04 阅读41 评论1 字号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?



eircQ 2010-07-25 11:43 发表评论
]]>
þþƷƷƷ| þþþAV| þþþһƷɫav| ŷƷһþ| ޾Ʒһþþ| 99þerֻоƷ18| 94þù׾Ʒ| þۺϾƷһ| aëƬþѲ| þAV뾫Ʒɫҹ鶹| þ91Ʒþ91ۺ| 91ɫۺϾþѷ| þۺ϶㼤þ| þ99ù龫Ʒ66| þþþùһ | ޾ƷþþþþĻ | žžþþƷ| þAV˳׽| þþþùƷ| ޹˾þۺ| 99þþƷһ| þùҹƷһ| þרƷ| þùƷһƷ| ˾ƷۺϾþþ| þþƷ| Ʒ99þþþƷ | þþþó˾ƷĻ | ٸۺϾþĻ| ξþ99ƷþþþþС˵ | þ99һ| þþƷ| þþþavר | þþŷղa| þ㽶߿ۿ| ݺɫþۺͼƬ| þ99Ʒ| þþƷ2020| þ| һһþþƷۺ| ɫ͵͵þһ|