2.1检索
数组是我们经常使用到的东西,一个例子就是储存静态的表格式数据。在实际应用中,我们往往需要找到数组中的特定数据。对于这种问题,终止整个搜索的一种处理方法是传递一个数组长度参数,而这里采取在数组最后放一个NULL作为结束参数。使用一个数组数据寻找函数作为遍历。
char *flab[] = {
"actually",
"just",
"quite",
"really",
NULL
};
int lookup(char *word, char *array[])
{
int i;
for (i = 0; array[i]; i++)
{
if (strcmp(word, array[i]) == 0)
{
return i;
}
return -1;
}
}
这里采用的算法是顺序搜索,虽然简单,但是工作量却与检索数据的数目成正比,因此也被称为线性搜索。
而对于那些较大的、排好序的算法,我们一般使用二分法进行,二分法将以对数形式进行数据搜索,在数据庞大的情况下有很好的效果。
2.2排序
如果我们要对某一个数据集进行反复检索,那么先对数组进行排序则是很有必要的。快速排序应该是目前为止最好的排序算法之一。它的实现也很简单:
我们使用一个基准值(随机选的)将整个数组分为两组:
“小的”小于基准值的元素、“大的”大于基准值的元素
递归地这两个组做排序。
而当这个过程结束的时候,整个数组就已经有序了。快速排序是一种实用而且高效的算法,人们对它做了深入研究,提出了许多变形。在这里要展示的大概是其中最简单的一种实现,但它肯定不是最快的。当然,仅仅是相对的,毕竟神理解递归。
对于这个算法,网上好多解释,我想说的就是,递归中传递参数的第一个值是数组地址,数组的头地址在不停变化;n也在不停变化,直到递归结束。
#include "stdafx.h"
#include "stdlib.h"
#include <iostream>
using namespace std;
void quicksort(int v[], int n);
void swap(int v[], int i, int j);
int main()
{
int shuzu[10] = { 8, 1, 2, 6, 4, 5, 3, 7, 0, 9 };
quicksort(shuzu, 10);
for (int i = 0; i < 10; i++)
{
cout << shuzu[i] ;
}
return 0;
}
void quicksort(int v[], int n)
{
int i, last;
if (n <= 1)
{
return;
}
swap(v, 0, rand() % n);
last = 0;
for (i = 1; i < n; i++)
{
if (v[i] < v[0])
{
swap(v, ++last, i);
}
}
swap(v, 0, last);
quicksort(v, last);
quicksort(v + last + 1, n - last - 1);//这里加的是地址了
}
void swap(int v[], int i, int j)
{
int temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
当然,这种的快速排序依赖于很好的基准值,糟糕的基准值将会使算法的性能大打折扣。有很多更好的、改进的算法,但明显我们并不需要都理解他们。当我们要使用它们的时候,我们要做的就是把库文件包含在我们的程序之中。
2.3库
对于那些复杂而又常用的代码,C和C++的标准库中已经包含了他们,例如上文提到的排序算法。在C函数库中,排序函数的名字是qsort,在调用qsort时必须为它提供一个比较函数,因为在排序中需要比较两个值。由于这里的值可以是任何类型的,比较函数的参数是两个指向被比较数据的void*指针,在函数里应该把指针强制转换到适当类型,然后提取数据值加以比较,并返回结果(根据比较中的第一个值小于、等于或者大于第二个值,分别返回负数、零或者正数)。
也就是说,qsort函数需要一个比较函数的入口地址当作函数的输入之一,这个比较函数我们就可以自己进行定义,它可以是比较字符串的,也可以是比较整数的。我们以整数的比较进行示范:
qsort是定义在头文件<stdlib.h>中的快速排序集合算法,巧妙的设计可以快速的得到想要的结果。在C++中,qsort的函数定义为:
_ACRTIMP void __cdecl qsort(
_Inout_updates_bytes_(_NumOfElements * _SizeOfElements) void* _Base,
_In_ size_t _NumOfElements,
_In_ size_t _SizeOfElements,
_In_ int (__cdecl* _PtFuncCompare)(void const*, void const*)
);
其中第一个参数为数组名称,第二个是元素个数,第三个是数组中单个元素所占的空间,第四个就是我们输入的比较函数的函数入口地址,使用qsort,我们可以快速的得到从小到大排序好的数组。
qsort(arr, array_number, sizeof(arr[1]), icmp);
C++中也定义了一个二分搜索函数bsearch,它可以很好的和qsort联系在一起进行使用。与qsort类似,bsearch也要求一个指向比较函数的指针 (常用与qsort同样的函数 )。bsearch返回一个指针,指向检索到的那个元素;如果没找到有关元素,bsearch返回NULL。在使用的时候,我们定义一个指针来作为bsearch的返回值,这个指针的类型应该与数组的类型一致。
那么最后,总体的代码就是:
#include "stdafx.h"
#include "stdlib.h"
#include <iostream>
using namespace std;
int icmp(const void *p1, const void *p2);
const int array_number = 10;
int main()
{
int arr[array_number] = {6, 2, 4, 9, 0, 8, 3, 1, 7, 5};
int *pItem = NULL;
int key = 6;
qsort(arr, array_number, sizeof(arr[1]), icmp);
pItem = (int *)bsearch(&key, arr, array_number, sizeof(arr[1]), icmp);
if (pItem != NULL)
{
printf("%d is in the array.\n", *pItem);
}
else
{
printf("%d is not in the array.\n", key);
}
return 0;
}
int icmp(const void *p1, const void *p2)
{
int v1, v2;
v1 = *(int *)p1;
v2 = *(int *)p2;
if (v1 < v2)
{
return -1;
}
else if (v1 == v2)
{
return 0;
}
else
{
return 1;
}
}