查找的概念
搜索引擎用的是静态查找
代码(静态查找and动态查找)
<strong><span style="font-size:18px;">#include <stdio.h> #include <stdlib.h> #include <time.h> #include "SeqList.h" #define SIZE 20 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ void print_array(int a[], int len) { int i = 0; for(i=0; i<len; i++) { printf("%d, ", a[i]); } printf(" "); } int static_search(int a[], int len, int key) {//静态查找 int ret = -1; int i = 0; for(i=0; i<len; i++) { if( a[i] == key ) { ret = i; break; } } return ret; } void print_list(SeqList* list) { int i = 0; for(i=0; i<SeqList_Length(list); i++) { printf("%d, ", (int)SeqList_Get(list, i)); } printf(" "); } int dynamic_search(SeqList* list, int key) {//动态查找 int ret = -1; int i = 0; for(i=0; i<SeqList_Length(list); i++) { if( (int)SeqList_Get(list, i) == key ) { ret = i; SeqList_Delete(list, i); break; } } return ret; } int main(int argc, char *argv[]) { SeqList* list = SeqList_Create(SIZE); int a[SIZE] = {0}; int i = 0; int key = 0; int index = 0; srand((unsigned int)time(NULL)); for(i=0; i<SIZE; i++) { a[i] = rand() % 100; SeqList_Insert(list, (SeqListNode*)(rand() % 100), i); //加入链表 动态查找 } key = rand() % 100; printf("Static Search Demo "); printf("Key: %d ", key); printf("Array: "); print_array(a, SIZE); index = static_search(a, SIZE, key); if( index >= 0 ) { printf("Success: a[%d] = %d ", index, a[index]); } else { printf("Failed! "); } printf("Dynamic Search Demo "); printf("Key: %d ", key); printf("List: "); print_list(list); index = dynamic_search(list, key); if( index >= 0 ) { printf("Success: list[%d] = %d ", index, key); } else { printf("Failed! "); } print_list(list); return 0; }</span></strong>
小结
顺序表和有序表查找
顺序表查找
<strong><span style="font-size:18px;">#include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 20 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ void print_array(int a[], int begin, int end) { int i = 0; for(i=begin; i<=end; i++) { printf("%d, ", a[i]); } printf(" "); } int another_search(int a[], int len, int key) { int ret = len; a[0] = key; //优化顺序查找 while( a[ret] != key ) {//只需比较一次,提高效率 ret--; } return ret; } int main(int argc, char *argv[]) { int a[SIZE + 1] = {0}; int i = 0; int key = 0; int index = 0; srand((unsigned int)time(NULL)); for(i=1; i<=SIZE; i++) { a[i] = rand() % 100; } key = rand() % 100; printf("Another Search Demo "); printf("Key: %d ", key); printf("Array: "); print_array(a, 1, SIZE); index = another_search(a, SIZE, key); if( index > 0 ) { printf("Success: a[%d] = %d ", index, a[index]); } else { printf("Failed! "); } return 0; }</span></strong>
二分查找(有序查找的一种)
插值查找
插值查找的速度比二分查找快,但是插值查找需要进行浮点数计算,因此,从稳定性上,插值不如二分查找
小结
二分查找代码
<strong><span style="font-size:18px;">#include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 20 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ void println(int array[], int len) { int i = 0; for(i=0; i<len; i++) { printf("%d ", array[i]); } printf(" "); } void swap(int array[], int i, int j) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } void SelectionSort(int array[], int len) // O(n*n) { int i = 0; int j = 0; int k = -1; for(i=0; i<len; i++) { k = i; for(j=i; j<len; j++) { if( array[j] < array[k] ) { k = j; } } swap(array, i, k); } } //二分查找 int binary_search(int a[], int low, int high, int key) // O(logn) { int ret = -1; if( low <= high ) { int mid = (low + high) / 2; if( a[mid] == key ) { ret = mid; } else if( key < a[mid] ) { ret = binary_search(a, low, mid-1, key); } else if( key > a[mid] ) { ret = binary_search(a, mid+1, high, key); } } return ret; } //二分查找 int binary_search_ex(int a[], int low, int high, int key) // O(logn) {//循环代替递归 int ret = -1; while( low <= high ) { int mid = (low + high) / 2; if( a[mid] == key ) { ret = mid; break; } else if( key < a[mid] ) { high = mid - 1; } else if( key > a[mid] ) { low = mid + 1; } } return ret; } int interpolation_search(int a[], int low, int high, int key) {//插值查找 int ret = -1; while( (low <= high) && (a[low] <= key) && (key <= a[high]) ) { float fx = 1.0f * (key - a[low]) / (a[high] - a[low]); int mid = low + fx * (high - low); if( a[mid] == key ) { ret = mid; break; } else if( key < a[mid] ) { high = mid - 1; } else if( key > a[mid] ) { low = mid + 1; } } return ret; } int main(int argc, char *argv[]) { int a[SIZE] = {0}; int i = 0; int key = 0; int index = 0; srand((unsigned int)time(NULL)); for(i=1; i<=SIZE; i++) { a[i] = rand() % 100; } key = 50; printf("Binary Search Demo "); printf("Key: %d ", key); printf("Array: "); SelectionSort(a, SIZE); println(a, SIZE); index = interpolation_search(a, 0, SIZE-1, key); if( index > 0 ) { printf("Success: a[%d] = %d ", index, a[index]); } else { printf("Failed! "); } return 0; }</span></strong>
斐波那契数列
黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二,较大部分与较小部分之比等于整体与较大部分之比,其比值约为1:0.618或1.618:1。
0.618被公认为最具有审美意义的比例数字,这个数值的作用不仅仅体现在诸如绘画、雕塑、音乐、建筑等艺术领域,而且在管理、工程设计等方面也有着不可忽视的作用。因此被称为黄金分
割。
大家记不记得斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…….(从第三个数开始,后边每一个数都是前两个数的和)
然后我们会发现,随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,我们就可以将黄金比例运用到查找技术中。
代码
<strong><span style="font-size:18px;"> #include "stdafx.h" #include <memory> #include <iostream> using namespace std; const int max_size=20;//斐波那契数组的长度 /*构造一个斐波那契数组*/ void Fibonacci(int * F) { F[0]=0; F[1]=1; for(int i=2;i<max_size;++i) F[i]=F[i-1]+F[i-2]; } /*定义斐波那契查找法*/ int Fibonacci_Search(int *a, int n, int key) //a为要查找的数组,n为要查找的数组长度,key为要查找的关键字 { int low=0; int high=n-1; int F[max_size]; Fibonacci(F);//构造一个斐波那契数组F int k=0; while(n>F[k]-1)//计算n位于斐波那契数列的位置 ++k; int * temp;//将数组a扩展到F[k]-1的长度 temp=new int [F[k]-1]; memcpy(temp,a,n*sizeof(int)); for(int i=n;i<F[k]-1;++i) temp[i]=a[n-1]; while(low<=high) { int mid=low+F[k-1]-1; if(key<temp[mid]) { high=mid-1; k-=1; } else if(key>temp[mid]) { low=mid+1; k-=2; } else { if(mid<n) return mid; //若相等则说明mid即为查找到的位置 else return n-1; //若mid>=n则说明是扩展的数值,返回n-1 } } delete [] temp; return -1; } int _tmain(int argc, _TCHAR* argv[]) { int a[] = {0,16,24,35,47,59,62,73,88,99}; int key=100; int index=Fibonacci_Search(a,sizeof(a)/sizeof(int),key); cout<<key<<" is located at:"<<index; system("PAUSE"); return 0; } </span></strong>
斐波那契查找的核心是:
1)当key=a[mid]时,查找成功;
2)当key<a[mid]时,新的查找范围是第low个到第mid-1个,此时范围个数为F[k-1] - 1个,即数组左边的长度,所以要在[low, F[k - 1] - 1]范围内查找;
3)当key>a[mid]时,新的查找范围是第mid+1个到第high个,此时范围个数为F[k-2] - 1个,即数组右边的长度,所以要在[F[k - 2] - 1]范围内查找。
线性索引查找
索引的概念
线性索引
小结
思考:
一、数组中一个只出现一次的整数
题目:一个数组中,有一个数字只出现一次,其他数字都出现两次,写出程序找出这个数字。
思路:利用异或运算,如果是两个相同的数,那么他们的结果就是0,剩下的就是只出现一次的数。
代码如下:
<strong><span style="font-size:18px;">#include <stdio.h> //find a number,which appearing once in an array int FindNumAppearOnce(int arr[], int iLen) { int iNumAppearOnce; iNumAppearOnce = arr[0]; for(int i = 1; i < iLen; i++) iNumAppearOnce ^= arr[i]; return iNumAppearOnce; } int main(void) { int arr[] = {1,2,2,3,3,4,4}; printf("%d ",FindNumAppearOnce(arr, 7)); return 0; } </span></strong>
二、数组中两个只出现一次的整数
思路:我们要让这两个只出现一次的数分别在两组,然后两组分别异或运算找出只出现一次的数。方法是,首先所有的数进行异或运算,得到的是只出现一次的两个数的异或运算结果。然后根据这个结果中第一次出现1的位(从右开始算),将数组分为两组。为什么可以分成两组?因为异或运算为1就是只出现一次的那两个数的那两个bit位不同,其他的数都抵消了。
代码如下:
<strong><span style="font-size:18px;">#include <stdio.h> int FindIndexOfBit1(int n) { int indexOfBit1 = 0; while(((1 & n) == 0) && indexOfBit1 < 32){ n >>= 1; indexOfBit1++; } return indexOfBit1; } int IsBit1(int n, int indexOfBit1){ n >>= indexOfBit1; return n & 1; } //find two number,which appearing once in an array //Input:arr - an array // iLen - the length of the array // pNum1 - number 1 founded // pNum2 - number 2 founded void FindNumAppearOnce(int arr[], int iLen, int *pNum1, int *pNum2) { if(iLen < 2) return; //get num1^num2 int resultOfExclusiveOr = 0; for(int i = 0; i < iLen; i++) resultOfExclusiveOr ^= arr[i]; //get index of the first bit int indexOfBit1 = FindIndexOfBit1(resultOfExclusiveOr); *pNum1 = *pNum2 = 0; for(int i = 0; i < iLen; i++){ if(IsBit1(arr[i], indexOfBit1)) *pNum1 ^= arr[i]; else *pNum2 ^= arr[i]; } } int main(void) { int arr[] = {1,5,2,2,3,3,4,4}; int a; int b; FindNumAppearOnce(arr, 8, &a, &b); printf("%d %d ", a,b); return 0; } </span></strong>
三、数组中3个只出现一次的数字
思路:
我们要把三个不同的数分开!首先分开两组,一个不同的和两个不同的各位一组。分开的思路:参考http://zhedahht.blog.163.com/blog/static/25411174201283084246412/
总之:x^a、x^b、x^c三个数字中,只有一个数字的第m位是1。作为它们的区分标准。
<strong><span style="font-size:18px;">#include <stdio.h> // int ValueOfBit1(int iNum) { return iNum & ~(iNum - 1); } // void Swap(int *pNum1, int *pNum2) { int iTemp; iTemp = *pNum1; *pNum1 = *pNum2; *pNum2 = iTemp; } // void PrintUniqueTwo(int arrNums[], int iLen) { int iXorResult = 0; for(int i = 0; i < iLen; i++) iXorResult ^= arrNums[i]; int iDiffBit = ValueOfBit1(iXorResult); int iNum1, iNum2; iNum1 = iNum2 = 0; for(int i = 0; i < iLen; i++) if(iDiffBit & arrNums[i]) iNum1 ^= arrNums[i]; else iNum2 ^= arrNums[i]; printf("%d %d ", iNum1, iNum2); } void PrintUniqueThree(int arrNums[], int iLen) { if(iLen < 3) return; //get a ^ b ^ c int iXorResult = 0; for(int i = 0; i < iLen; i++) iXorResult ^= arrNums[i]; //get fun(fun(x ^ a) ^ fun(x ^ b) ^ fun(x ^ b)) int iFunMultiResult = 0; for(int i = 0; i < iLen; i++) iFunMultiResult ^= ValueOfBit1(iXorResult ^ arrNums[i]); iFunMultiResult = ValueOfBit1(iFunMultiResult); //get the first unique number int iFirstUniqueNum = 0; for(int i = 0; i < iLen; i++) if(ValueOfBit1(arrNums[i] ^ iXorResult) == iFunMultiResult) iFirstUniqueNum ^= arrNums[i]; printf("%d ", iFirstUniqueNum); //move the first unique number to the end of the array for(int i = 0; i < iLen; i++) if(arrNums[i] == iFirstUniqueNum){ Swap(&arrNums[i], &arrNums[iLen - 1]); break; } PrintUniqueTwo(arrNums, iLen - 1); } int main(void) { int arrNums[] = {2,3,4,4,1,3,5,5,0}; PrintUniqueThree(arrNums, 9); return 0; } </span></strong>
int Find(int * a) { int i;//变量 for (i = 0 ;i<=1000;i++) { a[1000] += a[i]; } a[1000] -= (i*(i-1))/2 //i的值为1001 return a[1000]; }
<strong><span style="font-size:18px;">void FindRepeat(int array[], int length) { int index=array[length-1]-1; while ( true ) { if ( array[index]<0 ) break; array[index]*=-1; index=array[index]*(-1)-1; } cout<<"The repeat number is "<<index+1<<endl; }</span></strong>
<strong><span style="font-size:18px;">*/ void FindRepeat(int array[], int length, int num) { int index=array[length-1]-1; cout<<"The repeat number is "; while ( true ) { if ( array[index]<0 ) { num--; array[index]=length-num; cout<<index+1<<'t'; } if ( num==0 ) { cout<<endl; return; } array[index]*=-1; index=array[index]*(-1)-1; } }</span></strong>