算法基础部分整理-《图解算法》
2019你好!好好生活,好好工作!
1、二分查找法
基本思路:获取数组的中间值,将数组分割成两份,利用中间值跟指定的值进行比较,如果中间值大于指定的值,就在数组的左边进行查找;如果中间值小于指定值,就在数组的右边进行查找。如此循环的执行下去,最终找到符合的值。
优点:
1.速度快 2.比较次数少 3.性能好
缺点也很明显:
1.必须是一个有序的数组(升序或者降序)
2.适用范围:适用不经常变动的数组
运行时间:O(logn)
1 - (NSInteger)binary_searchInt:(NSArray *)array input:(NSInteger)input 2 { 3 4 NSInteger low = 0; 5 NSInteger high = array.count - 1; 6 while (low <= high) { 7 NSInteger mid = (low + high)/2; 8 NSNumber *tempNum = array[mid]; 9 if ([tempNum intValue] == input) { 10 return [tempNum intValue]; 11 12 }else if ([tempNum intValue] < input){ 13 low = mid + 1; 14 }else if ([tempNum intValue] > input){ 15 high = mid - 1; 16 } 17 } 18 return -1; 19 20 }
1 int binary_search(int a[],int iPut , int high){ 2 int low = 0; 3 while (low <= high){ 4 int mid = (low + high)/2; 5 int tempNum = a[mid]; 6 if (tempNum == iPut) { 7 return tempNum; 8 }else if (tempNum > iPut){ 9 high = mid - 1; 10 11 }else if(tempNum < iPut){ 12 low = mid + 1; 13 } 14 15 } 16 return -1; 17 }
2、选择排序
工作原理:
初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列;然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
优点:移动数据的次数已知(n-1 次);
缺点:比较次数多,费时
运行时间:O(n*n)
1 - (NSArray *)ocChoiceSort:(NSArray *)array 2 { 3 4 NSMutableArray *mutArray = [NSMutableArray arrayWithArray:array]; 5 for (int i = 0; i < mutArray.count - 1; i++) { 6 for (int j = i+1; j<mutArray.count; j++) { 7 if ([mutArray[i] intValue] > [mutArray[j] intValue]) { 8 NSNumber *tempNum = mutArray[i]; 9 [mutArray replaceObjectAtIndex:i withObject:mutArray[j]]; 10 [mutArray replaceObjectAtIndex:j withObject:tempNum]; 11 } 12 } 13 } 14 15 return [mutArray copy]; 16 }
1 void choiceSort(int a[],int len) 2 { 3 int i,j,temp; 4 for (i=0; i<len-1; i++) { 5 for (j=i+1; j<len; j++) { 6 if (a[i]>a[j]) { 7 temp = a[i]; 8 a[i]= a[j]; 9 a[j]= temp; 10 } 11 } 12 } 13 }
3、冒泡排序
工作原理:
从第一个数开始,依次和后面的数作比较,数值小的往上浮。例如:一共五个数,那么第一个数依次和后面四个数作比较。如果第一个数大于后面的数后,交换之后再比较。依次类推。
优点: 简单
缺点:效率不高
运行时间:O(n*n)
void maoPaoSort(int a[],int len) { for(int i =0;i < len - 1; i++) { for(int j = 0;j < len - 1-i; j++) { if(a[j] < a[j+1]) { int temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; } } } }
备注:冒泡和选择排序相似
4、快速排序
工作原理:
通过一轮的排序将序列分割成独立的两部分,其中一部分序列的关键字(这里主要用值来表示)均比另一部分关键字小。继续对长度较短的序列进行同样的分割,最后到达整体有序。在排序过程中,由于已经分开的两部分的元素不需要进行比较,故减少了比较次数,降低了排序时间。
详细描述:首先在要排序的序列 a 中选取一个中轴值,而后将序列分成两个部分,其中左边的部分 b 中的元素均小于或者等于 中轴值,右边的部分 c 的元素 均大于或者等于中轴值,而后通过递归调用快速排序的过程分别对两个部分进行排序,最后将两部分产生的结果合并即可得到最后的排序序列。
优点:极快,数据移动少.
缺点:不稳定
运行时间:O(logn)
这个算法也涉及到了递归调用
1 //left是数组开始排序的下标,right是结尾的下标 2 void quick_sort(int a[],int left,int right) 3 { 4 if (left >= right) { 5 return; 6 } 7 int i = left,j = right, key = a[left]; 8 while (i < j) { 9 //第一层while循环结束 表示y会根据key比较了一轮 10 11 //寻找的条件是:1、找到一个小于或者等于key的值(小于或大于取决于想升序还是降序)2、i==j 12 while (i<j && key<=a[j]) { 13 //由最后向前寻找 14 j--; 15 } 16 a[i] = a[j];//填i坑,挖出j坑:找到这样一个数后把它赋值给前面的被拿走的i的值 17 //这个 18 while (i<j && key>=a[i]) { 19 //由最前向后寻找 20 i++; 21 } 22 a[j] = a[i]; 23 } 24 a[i] = key; 25 //递归调用 26 quick_sort(a, left, i-1); 27 quick_sort(a, i+1, right); 28 }
5、递归
基本思想:
把规模大的问题转化为规模小的相似的子问题来解决。特别地,在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况,这也正是递归的定义所在。格外重要的是,这个解决问题的函数必须有明确的结束条件,否则就会导致无限递归的情况。
递归的三要素:
1、明确递归终止条件;
2、给出递归终止时的处理办法;
3、提取重复的逻辑,缩小问题规模。
递归的应用场景:
在我们实际学习工作中,递归算法一般用于解决三类问题:
(1). 问题的定义是按递归定义的(Fibonacci函数,阶乘,…);
(2). 问题的解法是递归的(有些问题只能使用递归方法来解决,例如,汉诺塔问题,…);
(3). 数据结构是递归的(链表、树等的操作,包括树的遍历,树的深度,…)。