算法的学习1.docx
- 文档编号:8467913
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:18
- 大小:235.77KB
算法的学习1.docx
《算法的学习1.docx》由会员分享,可在线阅读,更多相关《算法的学习1.docx(18页珍藏版)》请在冰豆网上搜索。
算法的学习1
数据结构的学习网站:
第一大类:
各种排序算法(插入排序、冒泡排序、选择排序,希尔排序,快速排序,堆排序,归并排序)
一、C#算法(插入排序)
每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当位置,直到全部记录插入完成为止。
(总是将所遍历到的数字插入到前面所有比自己大的数字的前面)
直接插入排序法
直接插入排序属于稳定的排序,时间复杂性为O(n2),空间复杂度为O
(1)。
publicstaticvoidSort(int[]list)
{
for(inti=1;i { intt=list[i]; intj=i; while((j>0)&&(list[j-1] { list[j]=list[j-1]; --j; } list[j]=t; } } 折半插入排序法 publicstaticvoidSort(int[]list) { intmid=0; for(inti=1;i { intlow=0; inthigh=i-1; inttemp=list[i]; while(low<=high) { mid=(low+high)/2; if(temp high=mid-1; else low=mid+1; } for(intk=i;k>mid;k--) { list[k]=list[k-1]; } list[low]=temp; } } 二、C#算法(冒泡排序) (总是将最大的数沉到最后面) publicstaticvoidSort(int[]list) { for(inti=1;i { for(intj=0;j { if(list[j]>list[j+1]) { inttemp=list[j]; list[j]=list[j+1]; list[j+1]=temp; } } } } publicstaticvoidSort(int[]list) { inti=list.Length; while(i>1) { intlastExchangeIndex=1; for(intj=1;j { if(list[j] { inttemp=list[j]; list[j]=list[j-1]; list[j-1]=temp; lastExchangeIndex=j; } } i=lastExchangeIndex; } } 三。 C#算法选择排序 (总是选择一个最小的数字放到第一位) publicstaticvoidSort(int[]list) { intmin; for(inti=0;i { min=i; for(intj=i+1;j { if(list[j] { min=j; } } intt=list[min]; list[min]=list[i]; list[i]=t; } } 四。 C#算法(四)快速排序 publicstaticvoidSort(int[]list,intlow,inthigh) { if(low { intpivot=list[low]; inti=low,j=high; while(i { while(i j--; list[i]=list[j]; while(i i++; list[j]=list[i]; } list[i]=pivot; Sort(list,low,i-1); Sort(list,i+1,high); } } 五。 C#算法(五)希尔排序 (就是在插入排序的基础上使用了一个增量inc,把一个数字分成了如干组进行插入排序,就是把插入排序中的1开始换成了inc开始) 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。 所有距离为dl的倍数的记录放在同一个组中。 先在各组内进行直接插人排序;然后,取第二个增量d2 dt=1(dt 该方法实质上是一种分组插入方法 publicstaticvoidSort(int[]list) { intinc=1; while(inc<=list.Length/9) inc=3*inc+1; for(;inc>0;inc/=3) { for(inti=inc;i { intt=list[i]; intj=i; while((j>0)&&(list[j-inc]>t)) { list[j]=list[j-inc]; j=j-inc; } list[j]=t; } } } 六、C#中的堆排序(0.0) 1 /* 2 堆排序 3 (1)用大根堆排序的基本思想 4 ① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区 5 ② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换, 6 由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key 7 ③ 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。 8 然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换, 9 由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n- 2].keys≤R[n-1..n].keys, 10 同样要将R[1..n-2]调整为堆。 11 …… 12 直到无序区只有一个元素为止。 13 (2)大根堆排序算法的基本操作: 14 ① 初始化操作: 将R[1..n]构造为初始堆; 15 ② 每一趟排序的基本操作: 将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。 16 注意: 17 ①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。 18 ②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。 19 堆排序和直接选择排序相反: 在任何时刻,堆排序中无序区总是在有序区之前, 20 且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。 21 */ 22 23 //生成大根堆 24 publicstaticvoidHeapAdjust(int[]SortData,intStartIndex,intLength) { while(2*StartIndex+1 { intMinChildrenIndex=2*StartIndex+1; if(2*StartIndex+2 { //比较左子树和右子树,记录最大值的Index if(SortData[2*StartIndex+1] { MinChildrenIndex=2*StartIndex+2; } } if(SortData[StartIndex] { //交换i与MinChildrenIndex的数据 inttmpData=SortData[StartIndex]; SortData[StartIndex]=SortData[MinChildrenIndex]; SortData[MinChildrenIndex]=tmpData; //堆被破坏,需要重新调整 StartIndex=MinChildrenIndex; } else { //比较左右孩子均大则堆未破坏,不再需要调整 break; } } return; } //堆排序 publicstaticvoidHeapSortData(int[]SortData) { inti=0; intLength=SortData.Length; //将Hr[0,Lenght-1]建成大根堆 for(i=Length/2-1;i>=0;i--) { HeapAdjust(SortData,i,Length); } for(i=Length-1;i>0;i--) { //与最后一个记录交换 inttmpData=SortData[0]; SortData[0]=SortData[i]; SortData[i]=tmpData; //将H.r[0..i]重新调整为大根堆 HeapAdjust(SortData,0,i); } return; } 七、C#中的归并算法 publicstaticvoidSort(int[]list,intlow,inthigh) { if(low>=high) return; intmid=(low+high)/2; Sort(list,low,mid); Sort(list,mid+1,high); Merge(list,low,mid,high); } publicstaticvoidMerge(int[]list,intlow,intmid,inthigh) { int[]array=newint[high-low+1]; intindex=0; intleft=low; intright=mid+1; while(left<=mid&&right<=high) { if(list[left] array[index++]=list[left++]; else array[index++]=list[right++]; } while(left<=mid) { array[index++]=list[left++]; } while(right<=high) { array[index++]=list[right++]; } for(index=0;index { list[low+index]=array[index]; } } 第二大类: 线性表(一般的线性表,栈,队列)的插入和删除 一、线性表的插入、删除 二、栈的插入、删除 三、队列的插入、删除 第三大类: 二叉树的遍历(前序,中序,后序) 一、二叉树的前序排列(递归、非递归) 二、二叉树的中序排列(递归、非递归) 三、二叉树的后序排列(递归、非递归) 第四大类: 图的遍历(深度优先,广度优先) 一、图的深度遍历 二、图的广度优先 第五大类: 线性查找(顺序查找),二分法查找(代码五行以内),散列查找,排序二叉树,Hash查找(处理冲突的方法)。 第六大类: KMP算法、BFS、DFS、同时熟练hash表(要熟,要灵活,代码要简) 第一阶段: 练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码, 因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打 出来. 1.最短路(Floyd、Dijstra,BellmanFord) 2.最小生成树(先写个prim,kruscal要用并查集,不好写) 3.大数(高精度)加减乘除 4.叉乘、判线段相交、然后写个凸包. 5.数学上的有: 辗转相除(两行内),线段交点、多角形面积公式. 6.调用系统的qsort,技巧很多,慢慢掌握. 7.任意进制间的转换 第二阶段: 练习复杂一点,但也较常用的算法。 如: 1.二分图匹配(匈牙利),最小路径覆盖 2.网络流,最小费用流。 3.线段树. 4.并查集。 5.熟悉动态规划的各个典型: LCS、最长递增子串、三角剖分、记忆化dp 6.博弈类算法。 博弈树,二进制法等。 7.最大团,最大独立集。 8.判断点在多边形内。 9.差分约束系统. 10.双向广度搜索、A*算法,最小耗散优先. 求一个数组的最大子数组之和? //Description: 求一个数组的子数组的最大的和 //============================================================================ #include usingnamespacestd; /** *两者的最大值 */ intmax(intx,inty){ return(x>y)? x: y; } /** *求一个数组的子数组的最大的和 *@description: 动态规划(将N规模的降低到N-1) *@detail: 假设已经知道(A[1],A[2]...A[n-1])中和最大的一段之和为All[1],且知道(A[1],A[2]...A[n-1]) *包含A[1]的和最大的一段和为Start[1],那么ALL[0]=max(A[0],A[0]+Start[1],All[1]);符合动态规划的 *无后效性,可以使用动态规划 */ intmaxSum(int*A,intn){ intnStart=A[n-1]; intnAll=A[n-1]; for(inti=n-2;i>-0;i--){ nStart=max(A[i],nStart+A[i]); nAll=max(nStart,nAll); } returnnAll; } intmain(){ intA[]={1,-2,3,5,5,9,-3,-2}; intsum=maxSum(A,sizeof(A)/sizeof(A[0])); cout< return0; } 五。 穷举搜索法 求解“百钱买百鸡”,公鸡每只5钱,母鸡每只3钱,小鸡每3只1钱 分析: x+y+z=100 5*x+3*y+z/3=100 1.voidmain() { intx,y,z; for(x=0;x<=100;x++) for(y=0;y<=100;y++) for(z=0;z<=100;z++) if(x+y+z=100&&5*x+3*y+z/3=100) printf("%d%d%d\n",x,y,z) } 2.voidmain() { intx,y,z; for(x=0;x<=20;x++) for(y=0;y<=33;y++) {z=100-x-y; if(z%3=0&&5*x+3*y+z/3=100) printf("%d%d%d\n",x,y,z) } } 六。 递归法 汉诺塔问题 (n阶汉诺塔问题)假设有三个分别命名为A,B和C的塔座,在塔座A上插有n个直径大小各不相同,按小到大编号为1,2,。 。 。 ,n的圆盘。 现要求将A轴上的n个圆盘移至C上并按同样顺序叠排,圆盘移动时必须遵循下列规则: 1)每次只能移动一个圆盘; 2)圆盘可以插在A,B和C中的任一塔座上; 3)任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。 #include voidmove(intn,chara,charc) { staticintstep=1; printf("step%2d: disk%d%c------->%c\n",step,n,a,c) step++; } voidHanoi(intn,chara,charb,charc) { if(n>1) { Hanoi(n-1,a,c,b);//先将前n-1个盘子从a通过c搬到b move(n,a,c);//将第n个盘子从a搬到c Hanoi(n-1,b,a,c);//再将这前n-1个盘子从b通过a搬到c } else { move(n,a,c);//将这1个盘子从a搬到c } } voidmain() {Hanoi(3,'A','B','C');} 七。 回溯法 求解迷宫问题。 迷宫用一个二维数组表示,其元素值有两个: 0和1,0表示通路,1表示阻塞,数组左上房[0][0]元素为迷宫入口,右下房[m-1][n-1]元素为迷宫的出口,现在寻找一条从入口到出口的通路(并不一定是最短的)。 #include #defineM12 #defineN15 voidmaze(intp[][],intm,intn) { intis[8]={0,1,1,1,0,-1,-1,-1};//行前进方向: 右,右下,下,左下,左,左上,上,右上 intjs[8]={1,1,0,-1,-1,-1,0,-1};//列前进方向: 右,右下,下,左下,左,左上,上,右上 intstack[3*M*N],*top; inti,j,v,g,h,jt; top=stack; i=j=v=0; if(p[0][0]! =0)//入口无路可走,提示无路,返回; { p[0][0]=4;printf("nopath! \n";return;) } while(top! =stack||v! =7) { g=i+is[v]; h=j+js[v];jt=0; if(g>-1&&g {if(g==m-1&&h==n-1&&p[m-1][n-1]==0) { p[i][j]=8;p[g][h]=8; return;//找到路径,停止返回; } if(p[g][h]==0) { p[g][h]=4; p[i][j]=8;//前一步位置上置8 top+=3; top[0]=i;top[1]=j;top[2]=v;//入栈,记录下前一步 i=g;j=h;v=0;jt=1; } } if(jt==0) { if(v<7)v++;//换一个方向 else { while(top! stack&&top[2]==7) { p[top[0]][top[1]]=4;//无路,栈中元素置为4,并弹栈 top-=3; } if(top! =stack) { i=top[0];j=top[1];v=top[2];//回溯,弹栈 p[i][j]=4;top-=3; } } } } printf("nopath! \n");//无路可走,提示无路,返回 return; } voidmain() { inti,j; intp[M][N]={ {0,1,0,0,0,1,1,0,0,0,1,1,1,1,1} {1,0,0,0,1,1,0,1,1,1,0,0,1,1,1} {0,1,1,0,0,0,0,1,1,1,1,0,0,1,1} {1,1,0,1,1,1,1,0,1,1,0,1,1,0,0} {1,1,0,1,1,1,1,0,1,1,0,1,1,0,0} {1,1,0,1,0,0,1,0,1,1,1,1,1,1,1} {0,0,1,1,0,1,1,1,0,1,0,0,1,1,1} {0,1,1,1,1,0,0,1,1,1,1,1,1,1,1} {0,0,1,1,0,1,1,0,1,1,1,1,1,0,1} {1,1,0,0,0,1,1,0,1,1,0,0,0,0,0} {0,0,1,1,1,1,1,0,0,0,1,1,1,1,0} {0,1,0,0,1,1,1,1,1,0,1,1,1,1,0} } maze(p,12,15) } 结果: {8,1,0,0,0,1,1,4,4,4,1,1,1,1,1} {1,8,8,8,1,1,4,1,1,1,4,4,1,1,1} {0,1,1,8,8,4,4,1,1,1,1,4,4,1,1} {1,1,8,1,1,1,1,4,1,1,4,1,1,4,4} {1,1,8,1,1,1,1,4,1,1,4,1,1,4,4} {1,1,8,1,0,0,1,4,1,1,1,1,1,1,1} {0,8,1,1,1,1,1,1,4,1,0,0,1,1,1} {8,1,1,1,1,8,8,1,1,1,1,1,1,1,1} {0,8,1,1,8,1,1,8,1,1,1,1,1,0,1} {1,1,8,8,8,1,1,8,1,1,8,8,8,8,8} {0,0,1,1,1,1,1,0,8,8,1,1,1,1,8} {0,1,0,0,1,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 学习