当前位置: 首页 > news >正文

外贸网站如何推广北京做网站推广

外贸网站如何推广,北京做网站推广,wordpress建站教程费用,今日顺德勒流新闻1. 查找的概念 在一堆数据中,找到我们想要的那个数据,就是查找,也称为搜索,很容易想到,查找算法的优劣,取决于两个因素: 数据本身存储的特点查找算法本身的特点 比如,如果数据存储…

1. 查找的概念

在一堆数据中,找到我们想要的那个数据,就是查找,也称为搜索,很容易想到,查找算法的优劣,取决于两个因素:

  • 数据本身存储的特点
  • 查找算法本身的特点

比如,如果数据存储是无序的,那么当我们想要在其中找到某个节点时,一般就只能对它们逐个比对。如果数据存储是有序且存放在一片连续的内存中,那么我们可以考虑从中间开始找(二分法)。因此可以看到,在实际应用中如果需要优化数据的查找(搜索)性能,我们主要从以上两方面入手,当然,有时数据的存储特性是无法更改的,那么此时就只能靠优化算法本身去达到提供程序性能的目的了。

2. 经典查找算法

2.1 顺序查找

顺序查找顾名思义,就是挨个找,这是一种不是算法的“算法”,最没办法的“办法”,简单直接,童叟无欺。时间复杂度就是 O(n)

适用情况:

  • 无序的数据
  • 无法(或不便于)对这些数据进行有效的整理

以下是示例代码

// 数据规模:100万
#define SCALE 1000*1000// 查找次数统计
static int count;int sequentialSearch(unsigned data[], int len, int n)
{for(int i=0; i<SCALE; i++){if(data[i] == n)return i;count++;}return -1;
}int main(int argc, char const *argv[])
{// 产生一系列无序数据srand(time(NULL));unsigned *data = calloc(SCALE, sizeof(unsigned));for(int i=0; i<SCALE; i++)data[i] = rand()%((int)pow(10, rand()%8+5));// 不进行任何数据整理,直接进行顺序查找unsigned n;printf("请输入你要找的正整数:\n");while(1){scanf("%u", &n);int pos = sequentialSearch(data, SCALE, n);if(pos == -1)printf("找不到你要的数据");elseprintf("你要找的数据第%d行", pos);printf("【找了%d次】\n", count);count = 0;}return 0;
}

以下是执行效果:

gec@ubuntu: ~$ ./sequential_search
请输入你要找的正整数:
132096806
你要找的数据第87行【找了87次】
951578948
你要找的数据第999999行【找了999999次】
951578949
找不到你要的数据【找了1000000次】

很显然,除非数据完全无序且无法整理,否则顺序查找的效率在大规模数据面前是非常低下的,因此一般情况下,对于大数据量的查找,我们都会尽量先对数据进行不同程度的整理。

2.2 分块查找

在一本字典中查找某个汉字的时候,一般是先找目录,在目录中找到对应拼音或笔画,然后直接翻到对应的页面再往下找,很显然这能大大提高查找的效率。

分块查找实质就是给数据建立索引,将查找的过程分成两个步骤:

  1. 在索引(目录)中找到数据所属分块
  2. 在所属分块中查找到该数据

以下例子中,先是产生系列长度和内容都随机的字符串,作为待查数据集。然后对这些字符串按首字符进行整理,形成字母表索引(目录)。最后利用索引提高查找效率。

核心代码示例

// 数据规模: 100万
#define SCALE  1000*1000 // 字符串总数
#define MAXLEN 20        // 字符串最大长度// 查找次数统计
static int count;char *random_string()
{int len = rand()%(MAXLEN);len = ((len<2)? 2 : len); // len: 2~19char *s = calloc(1, len);char letter[] = {'a', 'A'};for(int i=0; i<len-1; i++) // i: 0~[1~18]s[i] = letter[rand()%2]+rand()%26;return s;
}void create_index(char data[][MAXLEN], int **index)
{// 统计各个首字符出现的频次int n[52]={0}; // ['a', 'b', ... 'z', 'A', 'B', ... 'Z']for (int k = 0; k < SCALE; k++){// 小写字母[00~25],大写字母[26~51]int pos = ((data[k][0] >= 'a') ? (data[k][0]-'a') : (data[k][0]-'A'+26));n[pos]++;}// 给index分配内存// 每个字母分配一段存储以该字母为首的字符串所在的行号的内存// 第一个位置存储总行数,因此所需分配的内存单元数是1+n[i]。// 例如:// index[2] --> [ 242     3     22    213 ... ... 42513 46698]//   'c'    -->  总行数  第3行 第22行     ... ...for(int i=0; i<52; i++)index[i] = calloc(1+n[i], sizeof(int));// 记录每个字母出现的行号for(int i=0; i<SCALE; i++){int pos = ((data[i][0] >= 'a') ? (data[i][0]-'a') : (data[i][0]-'A'+26));int k = ++index[pos][0];index[pos][k] = i;}
}int main(int argc, char const *argv[])
{// 1. 产生随机字符串数据集//    假设每个字符串长度不超过MAXLEN个字符char (*data)[MAXLEN] = calloc(SCALE, MAXLEN);srand(time(NULL));for(int i=0; i<SCALE; i++){char *s = random_string();strncpy(data[i], s, strlen(s));free(s);}// 2. 按首字母建立索引(分块)int **index = calloc(52, sizeof(int *));create_index(data, index);// 3. 利用索引,进行查找char str[32];printf("请输入你要查找的字符串:\n");while(1){// 从键盘接收一个待查找的字符串并去掉回车符bzero(str, 32);fgets(str, 32, stdin);strtok(str, "\n");bool done = false;for(int i=1; i<SCALE; i++){// 小写字母[00~25],大写字母[26~51]int pos = ((str[0]>='a') ? (str[0]-'a') : (str[0]-'A'+26));count++;if(i<=index[pos][0] && strcmp(data[index[pos][i]], str) == 0){printf("你要找的字符串在第%d行", index[pos][i]);done = true;break;}else if(i > index[pos][0])break;}if(!done)printf("没有你要的字符串");printf("【找了%d次】\n", count);count=0;}return 0;
}

以下是执行效果:

gec@ubuntu: ~$ ./index_search
请输入你要查找的字符串:
e
你要找的字符串在第8行【找了1次】
sdf
你要找的字符串在第206096行【找了4078次】
ssHcbSJC
你要找的字符串在第396828行【找了7891次】

由于对数据进行了分块,引入了索引,查找效率大大提高,对于上述的100万个数据来说,假设以各个大小写字母开头的字符串概率相等,那么相当于将整体数据分成了52块,整体效率平局提升52倍,这个性能的提升的相当显著的,所付出的代价是:需要额外的内存空间存储索引表index,这是以空间换时间的经典思路。

2.3 二分查找

分块查找是在不对数据进行排序的情况下采用的颇为有效的查找办法,但如果待查找的数据本身是有序的,或者在查找前,可以对数据先进行排序(比如数据量虽然较大,但短期较稳定,无大面积更新),这种情况下使用二分查找可以进一步提升效率。

二分法的思路相当朴实无华:从中间开始找。既然数据是有序的,那么如果将待查找的节点跟中间节点对比,就可以以排除掉一半的数据,接着再在剩余的数据的中间开始找,又可以很快排除掉剩下的一半的数据,这种一半一半筛查数据的办法,就是所谓的二分法。

例如下图,想要在一系列有序(从小到大)的数据中,查找45,中间的节点数据是22,很显然左侧数据可以立即排除,45只可能存在于22右侧的序列中(若有):

img
二分查找算法示意图

假设有一系列有序数据,以下是二分查找算法的核心代码

// 数据规模: 100万
#define SCALE  1000*1000// 查找次数统计
static int count;int main(int argc, char const *argv[])
{// 1. 产生SCALE个随机整数序列unsigned *data = calloc(SCALE, sizeof(unsigned));srand(time(NULL));for(int i=0; i<SCALE; i++)data[i] = rand()%((int)pow(10, rand()%8+5));// 2. 排序quick_sort(data, SCALE);// 3. 进行二分查找unsigned n;printf("请输入你要查找的正整数:\n");while(1){scanf("%u", &n);int low, high, mid;low = 0, high = SCALE-1;bool found = false;while(low <= high){count++;mid = (low+high)/2;if(n == data[mid]){printf("你要找的数据在第%d行", mid);found = true;break;}if(n < data[mid])high = mid - 1;elselow = mid + 1;} if(!found)printf("找不到你要的数据");printf("【找了%d次】\n", count);count=0;}return 0;
}

以下是执行效果:

gec@ubuntu: ~$ ./binary_search
请输入你要查找的正整数:
1
你要找的数据在第6行【找了17次】
534
你要找的数据在第731行【找了12次】
6996
你要找的数据在第9534行【找了16次】
5863827
你要找的数据在第333334行【找了20次】

可见,二分查找的查找效率得到了质的飞跃!在最不利的情况下,100万个数据最多仅需查找20次就能锁定结果,这个效率大大优于顺序查找和分块查找。但别忘记,适合于用二分查找的场合是有条件的:数据是严格有序的。

http://www.mmbaike.com/news/90880.html

相关文章:

  • 如何选择企业网站建设公司济南百度seo
  • 音乐建设网站整站外包优化公司
  • 个体工商户经营范围做网站国内网络推广渠道
  • 重庆网站推广运营公司武汉seo全网营销
  • 网站在建设中页面网络优化seo是什么工作
  • wordpress网站模板怎么用海外新闻发布
  • 上海专业网站建设平台seochinazcom
  • 武汉做网站比较好的公司软文大全
  • 济南网站建设公司熊掌号b站入口2024已更新
  • 天河wap网站建设公司谷歌外贸网站推广
  • 网络营销的具体方法临沂seo推广
  • 海门城乡建设管理局网站天津网络关键词排名
  • 京东那个做快消的网站网络营销的主要方式和技巧
  • 阿里云 网站部署杭州网络排名优化
  • 青岛 网站备案win10必做的优化
  • 网站建设与管理报告书百度关键词查询工具免费
  • 做网站主流用什么语言曼联vs恩波利比分
  • 建设银行基金网站推广网络推广
  • 丽水网站建设企业最近几天发生的新闻大事
  • 随州网站推广哪家权威淘宝seo具体优化方法
  • 企业信息化平台百度seo优化教程
  • 做网站好接活吗网上推广产品哪个网好
  • 织梦网站关键词河北seo网络优化师
  • 网站转app生成器网站建设对企业品牌价值提升的影响
  • 无为网站定制如何优化关键词的排名
  • 桐庐网站制作营销软文推广平台
  • 网站怎么做不违法最新消息新闻
  • 蓟州区建设银行官方网站网站宣传推广策划
  • 网站域解析查询深圳经济最新新闻
  • 建立个人网站服务器西安网站建设推广专家