二分查找
1、查找某元素。循环条件 low <= high,最终结果位mid, 如果查询失败则返回-1。
int binSearch(int num[], int low, int high, int x){ int mid; while(low <= high){ //当搜索区间为空时结束 mid = low + (high - low) / 2; if(num[mid] == x) return mid; else if(num[mid] > x) high = mid - 1; else low = mid + 1; } return -1; }
2、查找第一个满足条件的元素。
1)被排好序的待搜索序列一定是从左到右先不满足条件,然后满足条件;
2)传入的high = N时,在搜索不到满足条件的数时,会返回N(假想N位置有数字); 若不想传入N,则需要在函数刚进入就判断,最后一个元素是否不满足条件,若不满足则说明查找失败,返回-1。
3)返回的是low而不是mid。
4)最后一个小于x的元素,相当于查找第一个大于等于x的元素的前一个。
/*返回第一个大于等于x的元素。num[N]数组应从小到大排序。 如果传入的high = N,则当序列中所有元素都小于x时,会返回N */ int binSearch(int num[], int low, int high, int x){ int mid; while(low < high){ //当low == high时结束搜索 mid = low + (high - low) / 2; if(num[mid] >= x) high = mid; //mid有可能就是结果,所以区间上限不能漏掉mid else low = mid + 1; } return low; //返回low而不是mid }
3、一般的套路是:固定一个端点(该端点顺序遍历),而对另一个端点采用二分法搜索。
4、使用二分法,搜索空间应该是有序的。
two points
1、使用2个指针,或者一头一尾,或两个都从头开始扫描。可以降低复杂度。主要关注指针移动的条件。
排序
1、归并排序
合并函数
void merge(int num[], int low1, int high1, int low2, int high2){ int temp[101]; int index = 0, i = low1, j = low2; while(i <= high1 && j <= high2){ if(num[i] < num[j]) temp[index++] = num[i++]; else temp[index++] = num[j++]; } while(i <= high1) temp[index++] = num[i++]; while(j <= high2) temp[index++] = num[j++]; for(int k = 0; k < index; k++) num[low1 + k] = temp[k]; }
排序, 非递归写法
void mergeSort(int num[], int len){
for(int step = 2; step <= len; step *= 2){ //初始步长为2, 逐步变为4、8、16 for(int i = 0; i < len; i += step){ //i + step为每个子区间的首部 int mid = i + step / 2 - 1; merge(num, i, mid, mid + 1, min(i + step - 1, len - 1)); } } }
递归写法
void mergeSort(int num[], int left, int right){ if(left < right){ int mid = (left + right) / 2; mergeSort(num, left, mid); mergeSort(num, mid + 1, right); merge(A, left, mid, mid + 1, right); } }
2、插入排序:将a[0]至a[i]视作有序序列,将a[i + 1]插入a[0]至a[i]中,使之有序。
void inser(int num[], int len){for(int i = 1; i < len; i++){ int temp = num[i]; int j = i - 1; while(j >= 0 && temp < num[j]){ num[j + 1] = num[j]; j--; } num[j + 1] = temp; } }
3、对一个数列进行不同方法的排序时注意,对N个方法应使用N个拷贝数组,若对一个数组连续排序就会出错。