二分查找、快速排序对比和详解
2016-03-24 22:19
681 查看
这两个都是用到分治的思想很容易搞混。而且即使binarySearch是用到分治也不一定意味着一定要用递归去实现,可以通过循环实现。二分查找和快速排序属于面试笔试的高频问题有必要总结一下。
由于循环相比递归少了很多内存分配和压栈的操作开销会少很多,所以binarySearch最好的实现方式是通过循环实现。binarySearch有一个大前提是数组是有序的,接下来没什么好解释的直接代码:
快速排序主要思想也是分治,在升序(降序)排序的过程中:
两个指针分别从数组头和尾部向中间遍历,当尾部指针遇到比枢纽小(大)的值,头部指针遇到比枢纽大(小),交换两个指针所指向的值的位置。
这里涉及到两个比较关键容易混淆的问题:
1.枢纽的选取。
2.停止条件的设置。
3.当头尾指针交叉后,枢纽和哪个指针进行交换。
如图所示当划分完毕后,在枢纽左边的应该是都比枢纽小(大);在枢纽右边的应该都比枢纽大(小),总之他们相对于枢纽来说是相对有序的。所以最后枢纽所在的位置很关键。
枢纽的初始位置选择有两种最简单的方法:选头部和选尾部。
以下的解释统一以升序为例子
枢纽的初始位置选择有两种最简单的方法:选头部和选尾部。
这时候划分完毕之后交换的方案也有两种主要根据枢纽的选择位置来决定。
(1)如果枢纽选的是头部,那么划分完毕后要和尾指针进行位置交换。因为要求交换完成后,枢纽左边的都是小于枢纽的数,而此时在不越界的情况下尾指针所指位置是刚好小于枢纽。
(2)如果枢纽选的是尾部的指针,则划分完毕后要和头指针进行交换。因为此时头指针所指的位置恰好大于枢纽,因为在不越界的情况下枢纽元右侧的均要大于枢纽元。
停止条件:
停止条件的设置不要在循环判断体中设置,要在循环体内设置。理论上来讲每一次比对的停止条件都是头指针大于枢纽元素,尾指针指向小于枢纽元素。即使最后一次也不例外,因为要找分界点方便交换枢纽。
所以代码:
由于循环相比递归少了很多内存分配和压栈的操作开销会少很多,所以binarySearch最好的实现方式是通过循环实现。binarySearch有一个大前提是数组是有序的,接下来没什么好解释的直接代码:
int binarySearch(int *a,int l,int r,int number) { int mid = (l+r)/2; while(l<=r){ if(a[mid]<number) l = mid+1; else if(a[mid]>number) r = mid-1; else if(a[mid] == number ) return mid; mid = (r+l)/2; } return -1; }
快速排序主要思想也是分治,在升序(降序)排序的过程中:
两个指针分别从数组头和尾部向中间遍历,当尾部指针遇到比枢纽小(大)的值,头部指针遇到比枢纽大(小),交换两个指针所指向的值的位置。
这里涉及到两个比较关键容易混淆的问题:
1.枢纽的选取。
2.停止条件的设置。
3.当头尾指针交叉后,枢纽和哪个指针进行交换。
如图所示当划分完毕后,在枢纽左边的应该是都比枢纽小(大);在枢纽右边的应该都比枢纽大(小),总之他们相对于枢纽来说是相对有序的。所以最后枢纽所在的位置很关键。
枢纽的初始位置选择有两种最简单的方法:选头部和选尾部。
以下的解释统一以升序为例子
枢纽的初始位置选择有两种最简单的方法:选头部和选尾部。
这时候划分完毕之后交换的方案也有两种主要根据枢纽的选择位置来决定。
(1)如果枢纽选的是头部,那么划分完毕后要和尾指针进行位置交换。因为要求交换完成后,枢纽左边的都是小于枢纽的数,而此时在不越界的情况下尾指针所指位置是刚好小于枢纽。
(2)如果枢纽选的是尾部的指针,则划分完毕后要和头指针进行交换。因为此时头指针所指的位置恰好大于枢纽,因为在不越界的情况下枢纽元右侧的均要大于枢纽元。
停止条件:
停止条件的设置不要在循环判断体中设置,要在循环体内设置。理论上来讲每一次比对的停止条件都是头指针大于枢纽元素,尾指针指向小于枢纽元素。即使最后一次也不例外,因为要找分界点方便交换枢纽。
所以代码:
void myQuickSort(int *a,int left,int right) { if(left>=right) return; int l = left, r = right; int pivot = left;//枢纽元选择的是头部 for(;;) { while(*(a+l) <= *(a+pivot)&& l<right)//防止越界 l++; while(*(a+r) >= *(a+pivot)&& r>L)//防止越界 r--; if(l<r) myswap(a,l,r); else break;//如果属于指针位置交叉的情况则停止 } if(*(a+pivot)<*(a+r)) //如果此时尾指针指向的元素刚好大于枢纽元素 myswap(a,pivot,r);//枢纽和尾指针进行交换使得枢纽元右侧的元素全部大于枢纽元, myQuickSort(a,left,r-1); myQuickSort(a,r+1,right); } 选尾部作枢纽: void myQuickSort(int *a,int left,int right) { if(left>=right) return; int l = left, r = right; int pivot = right;//枢纽元选的尾部 for(;;) { while(*(a+l) <= *(a+pivot)) l++; while(*(a+r) >= *(a+pivot)) r--; if(l<r) myswap(a,l,r); else break; } if(*(a+l) > *(a+pivot)) myswap(a,pivot,l);//和头指针交换 myQuickSort(a,left,l-1);//不包含pivot myQuickSort(a,l+1,right);//不包含pivot }
相关文章推荐
- 快速排序
- 只有程序员看的懂的面试圣经|如何拿下编程面试
- 下一次技术面试时要问的 3 个重要问题
- PHP程序员面试 切忌急功近利(更需要注重以后的发展)
- C#快速排序算法实例分析
- C++二分查找在搜索引擎多文档求交的应用分析
- C++快速排序的分析与优化详解
- C语言编程中实现二分查找的简单入门实例
- C#二分查找算法实例分析
- C#常见算法面试题小结
- js实现数组冒泡排序、快速排序原理
- php简单实现快速排序的方法
- Java 快速排序(QuickSort)原理及实现代码
- 快速排序和分治排序介绍
- java 算法之快速排序实现代码
- php 面试碰到过的问题 在此做下记录
- asp.net 面试+笔试题目第1/2页
- Java实现快速排序算法(Quicktsort)
- Java中的数组排序方式(快速排序、冒泡排序、选择排序)
- 快速排序的原理及java代码实现