算法详解.docx
- 文档编号:10003094
- 上传时间:2023-02-07
- 格式:DOCX
- 页数:21
- 大小:24.62KB
算法详解.docx
《算法详解.docx》由会员分享,可在线阅读,更多相关《算法详解.docx(21页珍藏版)》请在冰豆网上搜索。
算法详解
折半查找
又称二分查找。
使用条件:
有序集合。
算法思想:
先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或者不找到为止。
关键点在于比较中间位置所记录的关键字和给定值的比较,如果比给定值大(这里假设集合从小到大排列)那么可以缩小区间范围(集合开始-->中间位置的上一位),在比较该区间的中间位置所记录的关键字与给定值,依次循环到找到或者找不到位置。
举例编程:
这里有一个整数数据inta[10]={1,5,10,13,17,23,65,77,81,93};
(1)这是递归(感谢园友zdd指出这里判断条件的错误,应该改为if(min>max)
//折半查找
//数组必须按照一定的顺序
//参数:
最大,最小,目标(参数类型为整数)
int BinarySearch(int min,int max,int num)
{
if(min==max)return -1;
int mid=(min+max)/2;
if(a[mid]==num)return mid;
else if(a[mid] { return BinarySearch(mid+1,max,num); } else { return BinarySearch(min,mid-1,num); } } (2)非递归 //非递归算法 int BinarySearch_F(int num) { int min=0; int max=9; int mid; while(min<=max) { mid=(min+max)/2; if(a[mid]==num)return mid; else if(a[mid]>num)max=mid-1; else min=mid+1; } return -1; } 性能分析: 时间复杂度O(logn) 插入排序 使用条件: 可对比大小的集合。 算法思想: 将一个记录插入到已排好序的有序列中,从而得到一个新的,记录数增1的有序序列。 待插记录依次比较已经排好序列,如果序列数大于该待插记录,那么该序列往后挪一位,直到找到序列小于待插记录,那么此时插入到该序列的后一个位置,依次上面操作,直至插完位置。 举例编程: intb[10]={77,1,65,13,81,93,10,5,23,17}将其排序 //插入排序 //这里temp是哨兵位 //从小到大 void InsertSort() { int temp; int j; for(int i=1;i<10;i++) { temp=b[i]; for(j=i-1;j>=0;j--) { if(b[j]>temp) { b[j+1]=b[j]; } else { break; } } b[j+1]=temp; } cout<<"thesortis: "; for(int i=0;i<10;i++) { cout< } cout< } 性能分析: 时间复杂度O(n^2) 索引查找 索引查找是在索引表和主表(即线性表的索引存储结构)上进行的查找。 索引查找的过程是: 1) 首先根据给定的索引值K1,在索引表上查找出索引值等于KI的索引项,以确定对应予表在主表中的开始位置和长度, 2) 然后再根据给定的关键字K2,茬对应的子表中查找出关键字等于K2的元素(结点)。 对索引表或子表进行查找时,若表是顺序存储的有序表,则既可进行顺序查找,也可进行二分查找,否则只能进行顺序查找。 一提到“索引”,估计大家第一反应就是“数据库索引”,对的,其实主键建立“索引”,就是方便我们在海量数据中查找。 实现索引查找时常使用的三个术语: 1) 主表: 这个很简单,要查找的对象。 2) 索引项: 一般我们会用函数将一个主表划分成几个子表,每个子表建立一个索引,这个索引叫做索引项。 3) 索引表: 索引项的集合也就是索引表。 一般“索引项”包含三种内容: index,start ,lemgth 第一: index,也就是索引指向主表的关键字。 第二: start,也就是index在主表中的位置。 第三: length, 也就是子表的区间长度。 代码实现: [java] viewplaincopy 1.public class IndexSearch { 2. 3. // 主表 4. static int[] students = { 101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 201, 202, 5. 203, 204, 0, 0, 0, 0, 0, 0, 301, 302, 303, 0, 0, 0, 0, 0, 0, 0 }; 6. // 索引表 7. static IndexItem[] indexItem = { new IndexItem(1, 0, 5), 8. new IndexItem(2, 10, 4), new IndexItem(3, 20, 3), }; 9. 10. // 查找数据 11. public static int indexSearch(int key) { 12. IndexItem item = null; 13. 14. // 建立索引规则 15. int index = key / 100; 16. 17. // 首先去索引找 18. for (int i = 0; i < indexItem.length; i++) { 19. if (indexItem[i].index == index) { 20. item = new IndexItem(index, indexItem[i].start, 21. indexItem[i].length); 22. break; 23. } 24. } 25. 26. // 如果item为null,则说明在索引中查找失败 27. if (item == null) 28. return -1; 29. 30. for (int i = item.start; i < item.start + item.length; i++) { 31. if (students[i] == key) { 32. return i; 33. } 34. } 35. return -1; 36. } 37. 38. // / 插入数据 39. public static int insert(int key) { 40. IndexItem item = null; 41. // 建立索引规则 42. int index = key / 100; 43. int i = 0; 44. for (i = 0; i < indexItem.length; i++) { 45. // 获取到了索引 46. if (indexItem[i].index == index) { 47. item = new IndexItem(index, indexItem[i].start, 48. indexItem[i].length); 49. break; 50. } 51. } 52. if (item == null) 53. return -1; 54. // 更新主表 55. students[item.start + item.length] = key; 56. // 更新索引表 57. indexItem[i].length++; 58. return 1; 59. } 60. 61. public static void main(String[] args) { 62. int value = 205; 63. // 将205插入集合中,过索引 64. int index = insert(value); 65. insert(308); 66. 67. // 如果插入成功,获取205元素所在的位置 68. if (index == 1) { 69. System.out.println("\n插入后数据: " + Arrays.toString(students)); 70. System.out.println("\n数据元素: 205在数组中的位置为 " + indexSearch(205) + "位"); 71. } 72. 73. } 74. 75.} 76. 77.// 索引项实体 78.class IndexItem { 79. // 对应主表的值 80. public int index; 81. // 主表记录区间段的开始位置 82. public int start; 83. // 主表记录区间段的长度 84. public int length; 85. 86. public IndexItem() { 87. } 88. 89. public IndexItem(int index, int start, int length) { 90. this.index = index; 91. this.start = start; 92. this.length = length; 93. } 94.} 95. 96.运行结果: 97.原数据为: [101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 201, 202, 203, 204, 0, 0, 0, 0, 0, 0, 301, 302, 303, 0, 0, 0, 0, 0, 0, 0] 98. 99.插入后数据: [101, 102, 103, 104, 105, 0, 0, 0, 0, 0, 201, 202, 203, 204, 205, 0, 0, 0, 0, 0, 301, 302, 303, 308, 0, 0, 0, 0, 0, 0] 100. 101.数据元素: 205在数组中的位置为 14位 插入排序(InsertionSort)的基本思想是: 每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当位置,直到全部记录插入完成为止。 本节介绍两种插入排序方法: 直接插入排序和希尔排序。 直接插入排序基本思想 1.直接插入排序的基本思想 直接插入排序(StraightInsertionSorting)的基本思想是: 把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。 把a[i]插入到a[0],a[1],...,a[i-1]之中的具体实施过程为: 先把a[i]赋值给变量t,然后将t依次与a[i-1],a[i-2],...进行比较,将比t大的元素右移一个位置,直到发现某个j(0<=j<=i-1),使得a[j]<=t或j为(-1),把t赋值给a[j+1]. 2、第i-1趟直接插入排序: 通常将一个记录R[i](i=2,3,…,n-1)插入到当前的有序区,使得插入后仍保证该区间里的记录是按关键字有序的操作称第i-1趟直接插入排序。 排序过程的某一中间时刻,R被划分成两个子区间R[1..i-1](已排好序的有序区)和R[i..n](当前未排序的部分,可称无序区)。 直接插入排序的基本操作是将当前无序区的第1个记录R[i]插人到有序区R[1..i-1]中适当的位置上,使R[1..i]变为新的有序区。 因为这种方法每次使有序区增加1个记录,通常称增量法。 插入排序与打扑克时整理手上的牌非常类似。 摸来的第1张牌无须整理,此后每次从桌上的牌(无序区)中摸最上面的1张并插入左手的牌(有序区)中正确的位置上。 为了找到这个正确的位置,须自左向右(或自右向左)将摸来的牌与左手中已有的牌逐一比较。 一趟直接插入排序方法 1.简单方法 首先在当前有序区R[1..i-1]中查找R[i]的正确插入位置k(1≤k≤i-1);然后将R[k..i-1]中的记录均后移一个位置,腾出k位置上的空间插入R[i]。 注意: 若R[i]的关键字大于等于R[1..i-1]中所有记录的关键字,则R[i]就是插入原位置。 2.改进的方法 一种查找比较操作和记录移动操作交替地进行的方法。 具体做法: 将待插入记录R[i]的关键字从右向左依次与有序区中记录R[j](j=i-1,i-2,…,1)的关键字进行比较: ①若R[j]的关键字大于R[i]的关键字,则将R[j]后移一个位置; ②若R[j]的关键字小于或等于R[i]的关键字,则查找过程结束,j+1即为R[i]的插入位置。 关键字比R[i]的关键字大的记录均已后移,所以j+1的位置已经腾空,只要将R[i]直接插入此位置即可完成一趟直接插入排序。 直接插入排序算法 1.算法描述 实现程序 voidinsert_sort(ElemTypea[],intn) //待排序元素用一个数组a表示,数组有n个元素 {inti,j; ElemTypet;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 详解