Java常用排序算法及性能测试集合

周末天气不好,在家无事,把常用排序算法理了一遍,收获不小,特写文章纪念。这些算法在学校的时候学过一遍,很多原理都忘记了。现在再回过头理解,结合自己的体会, 选用最佳的方式描述这些算法,以方便理解它们的工作原理和程序设计技巧。本文适合做java面试准备的材料阅读。

先附上一个测试报告:

  1. Arraylength:20000
  2. bubbleSort:766ms
  3. bubbleSortAdvanced:662ms
  4. bubbleSortAdvanced2:647ms
  5. selectSort:252ms
  6. insertSort:218ms
  7. insertSortAdvanced:127ms
  8. insertSortAdvanced2:191ms
  9. binaryTreeSort:3ms
  10. shellSort:2ms
  11. shellSortAdvanced:2ms
  12. shellSortAdvanced2:1ms
  13. mergeSort:3ms
  14. quickSort:1ms
  15. heapSort:2ms
通过测试,可以认为,冒泡排序完全有理由扔进垃圾桶。它存在的唯一理由可能是最好理解。希尔排序的高效性是我没有想到的;堆排序比较难理解和编写,要有宏观的思维。


[java] view plain copy
  1. packagealgorithm.sort;
  2. importjava.lang.reflect.Method;
  3. importjava.util.Arrays;
  4. importjava.util.Date;
  5. /**
  6. *Java常用排序算法及性能测试集合
  7. *
  8. *本程序集合涵盖常用排序算法的编写,并在注释中配合极其简单的特例讲解了各种算法的工作原理,以方便理解和吸收;
  9. *程序编写过程中吸收了很多维基百科和别人blog上面的例子,并结合自己的思考,选择或改进一个最容易让人理解的写法。
  10. *同时包含一个集中式的性能测试和正确性测试方法,方便观测。
  11. *@authorhttp://blog.csdn.net/sunxing007
  12. *转载请注明来自http://blog.csdn.net/sunxing007
  13. */
  14. publicclassSortUtil{
  15. //被测试的方法集合
  16. staticString[]methodNames=newString[]{
  17. "bubbleSort",
  18. "bubbleSortAdvanced",
  19. "bubbleSortAdvanced2",
  20. "selectSort",
  21. "insertSort",
  22. "insertSortAdvanced",
  23. "insertSortAdvanced2",
  24. "binaryTreeSort",
  25. "shellSort",
  26. "shellSortAdvanced",
  27. "shellSortAdvanced2",
  28. "mergeSort",
  29. "quickSort",
  30. "heapSort"
  31. };
  32. publicstaticvoidmain(String[]args)throwsException{
  33. //correctnessTest();
  34. performanceTest(20000);
  35. }
  36. /**
  37. *正确性测试<br>
  38. *简单地测试一下各个算法的正确性<br>
  39. *只是为了方便观测新添加的算法是否基本正确;<br>
  40. *@throwsException主要是反射相关的Exception;<br>
  41. */
  42. publicstaticvoidcorrectnessTest()throwsException{
  43. intlen=10;
  44. int[]a=newint[len];
  45. for(inti=0;i<methodNames.length;i++){
  46. for(intj=0;j<a.length;j++){
  47. a[j]=(int)Math.floor(Math.random()*len*2);
  48. }
  49. MethodsortMethod=null;
  50. sortMethod=SortUtil.class.getDeclaredMethod(methodNames[i],a.getClass());
  51. Objecto=sortMethod.invoke(null,a);
  52. System.out.print(methodNames[i]+":");
  53. if(o==null){
  54. System.out.println(Arrays.toString(a));
  55. }
  56. else{
  57. //兼顾mergeSort,它的排序结果以返回值的形式出现;
  58. System.out.println(Arrays.toString((int[])o));
  59. }
  60. }
  61. }
  62. /**
  63. *性能测试<br>
  64. *数组长度用参数len传入,每个方法跑20遍取耗时平均值;<br>
  65. *@paramlen数组长度建议取10000以上,否则有些算法会显示耗时为0;<br>
  66. *@throwsException主要是反射相关的Exception;<br>
  67. */
  68. publicstaticvoidperformanceTest(intlen)throwsException{
  69. int[]a=newint[len];
  70. inttimes=20;
  71. System.out.println("Arraylength:"+a.length);
  72. for(inti=0;i<methodNames.length;i++){
  73. MethodsortMethod=null;
  74. sortMethod=SortUtil.class.getDeclaredMethod(methodNames[i],a.getClass());
  75. inttotalTime=0;
  76. for(intj=0;j<times;j++){
  77. for(intk=0;k<len;k++){
  78. a[k]=(int)Math.floor(Math.random()*20000);
  79. }
  80. longstart=newDate().getTime();
  81. sortMethod.invoke(null,a);
  82. longend=newDate().getTime();
  83. totalTime+=(end-start);
  84. }
  85. System.out.println(methodNames[i]+":"+(totalTime/times)+"ms");
  86. //System.out.println(Arrays.toString(a));
  87. }
  88. }
  89. /**
  90. *最原始的冒泡交换排序;<br>
  91. *两层遍历,外层控制扫描的次数,内层控制比较的次数;<br>
  92. *外层每扫描一次,就有一个最大的元素沉底;所以内层的比较次数将逐渐减小;<br>
  93. *时间复杂度:平均:O(n^2),最好:O(n);最坏:O(n^2);
  94. *空间复杂度:O(1);
  95. */
  96. publicstaticvoidbubbleSort(int[]a){
  97. for(inti=0;i<a.length;i++){
  98. for(intj=0;j<a.length-i-1;j++){
  99. if(a[j]>a[j+1]){
  100. inttmp=a[j];
  101. a[j]=a[j+1];
  102. a[j+1]=tmp;
  103. }
  104. }
  105. }
  106. }
  107. /**
  108. *改进的冒泡法<br>
  109. *改进之处在于:设一个标志位,如果某趟跑下来,没有发生交换,说明已经排好了;<br>
  110. */
  111. publicstaticvoidbubbleSortAdvanced(int[]a){
  112. intk=a.length-1;
  113. booleanflag=true;
  114. while(flag){
  115. flag=false;
  116. for(inti=0;i<k;i++){
  117. if(a[i]>a[i+1]){
  118. inttmp=a[i];
  119. a[i]=a[i+1];
  120. a[i+1]=tmp;
  121. //有交换则继续保持标志位;
  122. flag=true;
  123. }
  124. }
  125. k--;
  126. }
  127. }
  128. /**
  129. *改进的冒泡法2<br>
  130. *改进之处在于吸收上面的思想(没有交换意味着已经有序),如果局部的已经是有序的,则后续的比较就不需要再比较他们了。<br>
  131. *比如:31425678,假如刚刚做完了2和4交换之后,发现这趟比较后续再也没有发生交换,则后续的比较只需要比到4即可;<br>
  132. *该算法就是用一个标志位记录某趟最后发生比较的地点;<br>
  133. */
  134. publicstaticvoidbubbleSortAdvanced2(int[]a){
  135. intflag=a.length-1;
  136. intk;
  137. while(flag>0){
  138. k=flag;
  139. flag=0;
  140. for(inti=0;i<k;i++){
  141. if(a[i]>a[i+1]){
  142. inttmp=a[i];
  143. a[i]=a[i+1];
  144. a[i+1]=tmp;
  145. //有交换则记录该趟最后发生比较的地点;
  146. flag=i+1;
  147. }
  148. }
  149. }
  150. }
  151. /**
  152. *插入排序
  153. *
  154. *关于插入排序,这里有几个约定,从而可以快速理解算法:<br>
  155. *i:无序表遍历下标;i<n-1;<br>
  156. *j:有序表遍历下表;0<=j<i;<br>
  157. *a[i]:表示当前被拿出来做插入排序的无序表头元素;<br>
  158. *a[j]:有序表中的任意元素;<br>
  159. *<br>
  160. *算法关键点:把数组分割为a[0~i-1]有序表,a[i~n-1]无序表;每次从无序表头部取一个,<br>
  161. *把它插入到有序表适当的位置,直到无序表为空;<br>
  162. *初始时,a[0]为有序表,a[1~n-1]为无序表;<br>
  163. *
  164. *时间复杂度:平均:O(n^2),最好:O(n);最坏:O(n^2);
  165. *空间复杂度:O(1);
  166. */
  167. publicstaticvoidinsertSort(int[]a){
  168. //从无序表头开始遍历;
  169. for(inti=1;i<a.length;i++){
  170. intj;
  171. //拿a[i]和有序表元素依次比较,找到一个恰当的位置;
  172. for(j=i-1;j>=0;j--){
  173. if(a[j]<a[i]){
  174. break;
  175. }
  176. }
  177. //如果找到恰当的位置,则从该位置开始,把元素朝后移动一格,为插入的元素腾出空间;
  178. if(j!=(i-1)){
  179. inttmp=a[i];
  180. intk;
  181. for(k=i-1;k>j;k--){
  182. a[k+1]=a[k];
  183. }
  184. a[k+1]=tmp;
  185. }
  186. }
  187. }
  188. /**
  189. *改进的插入排序1
  190. *改进的关键在于:首先拿无序表头元素a[i]和有序表尾a[i-1]比较,
  191. *如果a[i]<a[i-1],说明需要调整;调整的过程为:
  192. *从有序表尾开始,把有序表里面比a[i]大的元素都朝后移动,直到找到恰当的位置;
  193. */
  194. publicstaticvoidinsertSortAdvanced(int[]a){
  195. //遍历无序表;
  196. for(inti=1;i<a.length;i++){
  197. //如果无序表头元素小于有序表尾,说明需要调整;
  198. if(a[i]<a[i-1]){
  199. inttmp=a[i];
  200. intj;
  201. //从有序表尾朝前搜索并比较,并把大于a[i]的元素朝后移动以腾出空间;
  202. for(j=i-1;j>=0&&a[j]>tmp;j--){
  203. a[j+1]=a[j];
  204. }
  205. a[j+1]=tmp;
  206. }
  207. }
  208. }
  209. /**
  210. *改进的插入排序2
  211. *总体思想和上面相似,拿无序表头元素从有序表尾元素开始朝前比较,
  212. *如果a[i]比a[i-1]小,则把a[i]从有序表尾用冒泡交换的方式朝前移动,直到到达恰当的位置;
  213. */
  214. publicstaticvoidinsertSortAdvanced2(int[]a){
  215. //遍历无序表
  216. for(inti=1;i<a.length;i++){
  217. //拿a[i]从有序表尾开始冒泡;
  218. for(intj=i-1;j>=0&&a[j]>a[j+1];j--){//a[j+1]就是a[i]
  219. inttmp=a[j];
  220. a[j]=a[j+1];
  221. a[j+1]=tmp;
  222. }
  223. }
  224. }
  225. /**
  226. *快速排序<br>
  227. *算法的思想在于分而治之:先找一个元素(一般来说都是数组头元素),把比它大的都放到右边,把比它小的都放到左边;<br>
  228. *然后再按照这样的思想去处理两个子数组;下面说的子数组头元素通指用来划分数组的元素;<br>
  229. *<br>
  230. *下面程序关键点就在于!forward,low0++,high0--这些运算;这三个运算使得a[low0],a[high0]里面总有一个指向子数组头元素;<br>
  231. *可以用极端的情况来方便理解这三个值的运作:<br>
  232. *假如我的数列为0123456789,初始时forward=false,0作为子数组划分依据,很显然第一轮的时候不会发生任何交换,low0一直指向0,<br>
  233. *high0逐渐下降直到它指向0为止;同理可思考9876543210这个例子;<br>
  234. *<br>
  235. *时间复杂度:平均:O(nlogn),最好:O(nlogn);最坏:O(n^2);
  236. *空间复杂度:O(logn);要为递归栈提供空间
  237. *@parama待排序数组<br>
  238. *@paramlow子数组开始的下标;<br>
  239. *@paramhigh子数组结束的下标;<br>
  240. */
  241. publicstaticvoidquickSort(int[]a,intlow,inthigh){
  242. if(low>=high){
  243. return;
  244. }
  245. intlow0=low;
  246. inthigh0=high;
  247. booleanforward=false;
  248. while(low0!=high0){
  249. if(a[low0]>a[high0]){
  250. inttmp=a[low0];
  251. a[low0]=a[high0];
  252. a[high0]=tmp;
  253. forward=!forward;
  254. }
  255. if(forward){
  256. low0++;
  257. }
  258. else{
  259. high0--;
  260. }
  261. }
  262. low0--;
  263. high0++;
  264. quickSort(a,low,low0);
  265. quickSort(a,high0,high);
  266. }
  267. /**
  268. *快速排序的简单调用形式<br>
  269. *方便测试和调用<br>
  270. *@parama
  271. */
  272. publicstaticvoidquickSort(int[]a){
  273. quickSort(a,0,a.length-1);
  274. }
  275. /**
  276. *归并排序<br>
  277. *所谓归并,就是合并两个有序数组;归并排序也用了分而治之的思想,把一个数组分为若干个子数组;<br>
  278. *当子数组的长度为1的时候,则子数组是有序的,于是就可以两两归并了;<br>
  279. *<br>
  280. *由于归并排序需要分配空间来转储归并的结果,为了算法上的方便,归并算法的结果以返回值的形式出现;<br>
  281. */
  282. /**
  283. *合并两个有序数组
  284. *@parama有序数组1
  285. *@paramb有序数组2
  286. *@return合并之后的有序数组;
  287. */
  288. publicstaticint[]merge(int[]a,int[]b){
  289. intresult[]=newint[a.length+b.length];
  290. inti=0,j=0,k=0;
  291. while(i<a.length&&j<b.length){
  292. if(a[i]<b[j]){
  293. result[k++]=a[i];
  294. i++;
  295. }
  296. else{
  297. result[k++]=b[j];
  298. j++;
  299. }
  300. }
  301. while(i<a.length){
  302. result[k++]=a[i++];
  303. }
  304. while(j<b.length){
  305. result[k++]=b[j++];
  306. }
  307. returnresult;
  308. }
  309. /**
  310. *归并排序<br>
  311. *把数组从中间一分为二,并对左右两部分递归调用,直到数组长度为1的时候,开始两两归并;<br>
  312. *时间复杂度:平均:O(nlogn),最好:O(nlogn);最坏:O(nlogn);
  313. *空间复杂度:O(n);要为归并的结果分配空间
  314. *@param待排序数组;
  315. *@return有序数组;
  316. */
  317. publicstaticint[]mergeSort(int[]a){
  318. if(a.length==1){
  319. returna;
  320. }
  321. intmid=a.length/2;
  322. int[]leftPart=newint[mid];
  323. int[]rightPart=newint[a.length-mid];
  324. System.arraycopy(a,0,leftPart,0,leftPart.length);
  325. System.arraycopy(a,mid,rightPart,0,rightPart.length);
  326. leftPart=mergeSort(leftPart);
  327. rightPart=mergeSort(rightPart);
  328. returnmerge(leftPart,rightPart);
  329. }
  330. /**
  331. *选择排序<br>
  332. *和插入排序类似,它也把数组分割为有序区和无序区,所不同的是:<br>
  333. *插入排序是拿无序区的首元素插入到有序区适当的位置,而<br>
  334. *选择排序是从无序区中挑选最小的放到有序区最后;<br>
  335. *<br>
  336. *两层循环,外层控制有序区的队尾,内层用来查找无序区最小元素;<br>
  337. *
  338. *时间复杂度:平均:O(n^2),最好:O(n);最坏:O(n^2);
  339. *空间复杂度:O(1);
  340. *@parama
  341. */
  342. publicstaticvoidselectSort(int[]a){
  343. for(inti=0;i<a.length;i++){
  344. intminIndex=i;
  345. for(intj=i+1;j<a.length;j++){
  346. if(a[j]<a[minIndex]){
  347. minIndex=j;
  348. }
  349. }
  350. inttmp=a[i];
  351. a[i]=a[minIndex];
  352. a[minIndex]=tmp;
  353. }
  354. }
  355. /**
  356. *希尔排序<br>
  357. *其思想是把数组按等步长(/间距)划分为多个子序列,对各个子序列做普通的插入排序,<br>逐次降低步长,直到为1的时候最后再做一次普通的插入排序;
  358. *用一个极端的例子作比方,我有数列如下:<br>
  359. *[1,2,3,4,5,6,7,8,9,10];<br>
  360. *初始的时候,步长gap=5;则划分的子数组为[1,6],[2,7],[3,8],[4,9],[5,10];<br>对他们分别排序(当然由于本数组特殊,所以结果是不变的);<br>
  361. *然后gap=2=5/2;子数组为[1,3,5,7,9],[2,4,6,8,10];<br>
  362. *最后gap=1=2/2;做一次全局排序;<br>
  363. *<br>
  364. *希尔排序克服了插入/冒泡排序的弱点(一次只能把元素移动一个相邻的位置),<br>依靠大步长,可以把元素尽快移动到目标位置(或附近);<br>
  365. *希尔排序实际上是插入排序的变种。它适用于:当数组总体有序,个别需要调整的情况;这时候利用插入排序的优势,可以达到O(n)的效率;<br>
  366. *影响希尔算法的一个重要的因素是步长选择,一个好步长的优点是:后面的短步长排序不会破坏前面的长步长排序;<br>
  367. *怎么理解这种破坏呢?前面的长步长把一个较小的数移到了左面,但是在缩小步长之后有可能又被交换到了右面(因为它被分到了一个有很多比它更小的组);<br>
  368. *关于步长,可以查看http://zh.wikipedia.org上面关于希尔排序的页面;<br>
  369. *下面的程序是希尔排序最基础的写法,适合用来理解希尔排序思想;<br>
  370. *
  371. *时间复杂度:受步长影响较大,n/2步长的平均复杂度为n(logn)^2;
  372. */
  373. publicstaticvoidshellSort(int[]a){
  374. //控制间距;间距逐渐减小,直到为1;
  375. for(intgap=a.length/2;gap>0;gap/=2){
  376. //扫描每个子数组
  377. for(inti=0;i<gap;i++){
  378. //对每个字数组,扫描无序区;注意增量;
  379. //a[i]是初始有序区;
  380. for(intj=i+gap;j<a.length;j+=gap){
  381. //无序区首元素小于有序区尾元素,说明需要调整
  382. if(a[j]<a[j-gap]){
  383. inttmp=a[j];
  384. intk=j-gap;
  385. //从有序区尾向前搜索查找适当的位置;
  386. while(k>=0&&a[k]>tmp){
  387. a[k+gap]=a[k];
  388. k-=gap;
  389. }
  390. a[k+gap]=tmp;
  391. }
  392. }
  393. }
  394. }
  395. }
  396. /**
  397. *改进的希尔排序<br>
  398. *改进之处在于:上面的写法用一个for循环来区别对待每个字数组;而实际上是不必要的;<br>
  399. *a[0,1,...gap-1]作为所有子数组的有序区,a[gap,...n-1]作为所有字数组的无序区;<br>
  400. *<br>
  401. *该改进在时间效率上没有改进;只是让程序看起来更简洁;<br>
  402. *@parama
  403. */
  404. publicstaticvoidshellSortAdvanced(int[]a){
  405. //控制步长
  406. for(intgap=a.length/2;gap>0;gap/=2){
  407. //从无序区开始处理,把多个子数组放在一起处理;
  408. for(intj=gap;j<a.length;j++){
  409. //下面的逻辑和上面是一样的;
  410. if(a[j]<a[j-gap]){
  411. inttmp=a[j];
  412. intk=j-gap;
  413. while(k>=0&&a[k]>tmp){
  414. a[k+gap]=a[k];
  415. k-=gap;
  416. }
  417. a[k+gap]=tmp;
  418. }
  419. }
  420. }
  421. }
  422. /**
  423. *改进的希尔排序2<br>
  424. *在吸收shellSortAdvanced思想的基础上,采用insertAdvanced2的做法;<br>即无序区首元素通过朝前冒泡的形式移动的适当的位置;<br>
  425. *@parama
  426. */
  427. publicstaticvoidshellSortAdvanced2(int[]a){
  428. for(intgap=a.length/2;gap>0;gap/=2){
  429. for(inti=gap;i<a.length;i++){
  430. if(a[i]<a[i-gap]){
  431. for(intj=i-gap;j>=0&&a[j+gap]>a[j];j-=gap){
  432. inttmp=a[j];
  433. a[j]=a[j+gap];
  434. a[j+gap]=tmp;
  435. }
  436. }
  437. }
  438. }
  439. }
  440. /**
  441. *堆排序<br>
  442. *堆的定义:堆是一个完全,或近似完全的二叉树,堆顶元素的值大于左右孩子的值,左右孩子也需要满足这个条件;<br>
  443. *按照堆的定义,堆可以是大顶堆(maxHeap),或小顶堆(minHeap);<br>
  444. *一般用数组即可模拟二叉树,对于任意元素i,左孩子为2*i+1,右孩子为2*i+2;父节点为(i-1)/2;
  445. *
  446. *时间复杂度:平均:O(nlogn);
  447. *空间复杂度:O(1);
  448. *@parama
  449. */
  450. publicstaticvoidheapSort(int[]a){
  451. //先从最后一个非叶子节点往上调整,使满足堆结构;
  452. for(inti=(a.length-2)/2;i>=0;i--){
  453. maxHeapAdjust(a,i,a.length);
  454. }
  455. //每次拿最后一个节点和第一个交换,然后调整堆;直到堆顶;
  456. for(inti=a.length-1;i>0;i--){
  457. inttmp=a[i];a[i]=a[0];a[0]=tmp;
  458. maxHeapAdjust(a,0,i);
  459. }
  460. }
  461. /**
  462. *调整堆<br>
  463. *把以i为跟节点的二叉树调整为堆;<br>
  464. *可以这么来思考这个过程:这个完全二叉树就像一个金字塔,塔顶的小元素沿着树结构,往下沉降;<br>
  465. *调整的结果是最大的元素在金字塔顶,然后把它从堆中删除(把它交换到堆尾,然后堆收缩一格);<br>
  466. *堆排序快的原因就是根据二叉树的特点,一个节点要沉降到合适的位置,只需要logn步;同时前期调整的结果(大小顺序)会被记录下来,从而加快后续的调整;<br>
  467. *@parama待排数组
  468. *@parami堆顶
  469. *@paramlen堆长度
  470. */
  471. publicstaticvoidmaxHeapAdjust(int[]a,inti,intlen){
  472. inttmp=a[i];
  473. //j是左孩子节点
  474. intj=i*2+1;
  475. //
  476. while(j<len){
  477. //从左右孩子中挑选大的
  478. //j+1是右孩子节点
  479. if((j+1)<len&&a[j+1]>a[j]){
  480. j++;
  481. }
  482. //找到恰当的位置就不再找
  483. if(a[j]<tmp){
  484. break;
  485. }
  486. //否则把较大者沿着树往上移动;
  487. a[i]=a[j];
  488. //i指向刚才的较大的孩子;
  489. i=j;
  490. //j指向新的左孩子节点;
  491. j=2*i+1;
  492. }
  493. //把要调整的节点值下沉到适当的位置;
  494. a[i]=tmp;
  495. }
  496. /**
  497. *二叉树排序<br>
  498. *二叉树的定义是嵌套的:<br>节点的值大于左叶子节点的值,小于右叶子节点的值;叶子节点同样满足这个要求;<br>
  499. *二叉树的构造过程就是排序的过程:<br>
  500. *先构造跟节点,然后调用add方法添加后续节点为跟节点的子孙节点;这个过程也是嵌套的;<br>
  501. *<br>
  502. *中序遍历二叉树即得到有序结果;<br>
  503. *二叉树排序用法特殊,使用情形要视情况而定;<br>
  504. *
  505. *时间复杂度:平均:O(nlogn);
  506. *空间复杂度:O(n);
  507. *
  508. *@parama
  509. */
  510. publicstaticvoidbinaryTreeSort(int[]a){
  511. //构造一个二叉树节点内部类来实现二叉树排序算法;
  512. classBinaryNode{
  513. intvalue;
  514. BinaryNodeleft;
  515. BinaryNoderight;
  516. publicBinaryNode(intvalue){
  517. this.value=value;
  518. this.left=null;
  519. this.right=null;
  520. }
  521. publicvoidadd(intvalue){
  522. if(value>this.value){
  523. if(this.right!=null){
  524. this.right.add(value);
  525. }
  526. else{
  527. this.right=newBinaryNode(value);
  528. }
  529. }
  530. else{
  531. if(this.left!=null){
  532. this.left.add(value);
  533. }
  534. else{
  535. this.left=newBinaryNode(value);
  536. }
  537. }
  538. }
  539. /**
  540. *按中序遍历二叉树,就是有序的。
  541. */
  542. publicvoiditerate(){
  543. if(this.left!=null){
  544. this.left.iterate();
  545. }
  546. //在测试的时候要把输出关掉,以免影响性能;
  547. //System.out.print(value+",");
  548. if(this.right!=null){
  549. this.right.iterate();
  550. }
  551. }
  552. }
  553. BinaryNoderoot=newBinaryNode(a[0]);
  554. for(inti=1;i<a.length;i++){
  555. root.add(a[i]);
  556. }
  557. root.iterate();
  558. }

原文地址:http://blog.csdn.net/sunxing007/article/details/9005471

你可能感兴趣的:(java)