目录:

一:查找的概念与术语

二:折半查找

三:二叉排序树

四:平衡二叉树

五:B-树

六:B+树

七:散列表

八:实践题:QQ帐户的申请与登陆

九:自我总结

一、查找的概念与术语

  (一)查找表

    查找表是由同一类型的数据元素(或记录)构成的集合。

  (二)关键字

    关键字是数据元素(或记录)中某个数据项的值,用它可以标识一个数据元素(或记录)。

  (三)查找

    查找是指根据给定的某个值,在查找表中确定一个其关键字等于给定值得记录或数据元素。

  (四)动态查找表和静态查找表

    若在查找的同时对表作修改操作(如插入和删除),则相应的表称之为动态查找表,否则称之为静态查找表。

  (五)平均查找长度(ASL)

    为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望值,成为查找算法在查找成功时的平均查找长度。

    对于含有n个记录的表,查找成功时的平均查找长度为P1*C1+P2*C2+....+Pi*Ci+.....+Pn*Cn

    其中,Pi为查找表中第i个记录的概率,Ci为找到表中其关键字与给定值相等的第i个记录时,和给定值已进行过比较的关键字个数。

二、折半查找

  折半查找也称二分查找,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

  折半查找的查找过程为:从表的中间记录开始,如果给定值和中间记录的关键字相等,则查找成功;如果给定值大于或者小于中间记录的关键字,则在表中大于或小于中间记录的那一半

中查找,这样重复操作,直到查找成功,或者在某一步中查找区间为空,则代表查找失败。

  

三:二叉排序树

  二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:

  (一)若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;

  (二)若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值;

  (三)它的左、右子树也分别为二叉排序树。

   

  如下图就为一棵二叉排序树

四、平衡二叉树

  平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树AVL替罪羊树Treap伸展树等。 最小二叉平衡树的节点总数的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

  如下图就为一棵平衡二叉树

五、B-树

  一棵m阶的B-树,或为空树,或为满足下列特性的m叉树:
  (一)树中每个节点至多有m棵子树;
  (二)若根节点不是叶子节点,则至少有两棵子树;
  (三)除根之外的所有非终端节点至少有⌈m/2⌉棵子树;
  (四)所有的叶子结点都出现在同一层次上,并且不带信息,通常称为失败节点;
  (五)所有的非终端节点最多有m-1个关键字
 
  如图

六、B+树

  一棵m阶的B+树和m阶的B-树的差异在于:

  (一)有n棵子树的节点中含有n个关键字;

  (二)所有的叶子结点中包含了全部关键字的信息,以及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序连接;

  (三)所有的非终端节点可以看成是索引部分,节点中仅含有其子树中的最大(或最小)关键字

  如图

七、散列表

  (一)散列法中常用的几个术语:

    1.散列函数和散列地址:在记录的存储位置p和其关键字key之间建立一个确定的对应关系H,使p=H(key),称这个对应关系H为散列函数,p为散列地址。
    2.散列表:一个有限连续的地址空间,用以存储按散列函数计算得到相应散列地址的数据记录。
    3.冲突和同义词:对不同的关键字可能得到同一散列地址,这种现象成为冲突。具有相同函数值的关键字对该散列函数来说称作同义词,key1和key2互称为同义词。

  (二)散列函数的构造方法:

    1.数字分析法

    2.平方取中法

    3.折叠法

    4.除留余数法 (假设散列表表长为m,选择一个不大于m的数p,用p去除关键字,除后所得余数为散列地址)

  (三)处理冲突的办法

    1.开放地址法

      (1)线性探测法

      (2)二次探测法

      (3)伪随机探测法

    2.链地址法(下面做实践题目用到)

  
八:实践题:QQ帐户的申请与登陆

实现QQ新帐户申请和老帐户登陆的简化版功能。最大挑战是:据说现在的QQ号码已经有10位数了。

输入格式:

输入首先给出一个正整数N(≤),随后给出N行指令。每行指令的格式为:“命令符(空格)QQ号码(空格)密码”。其中命令符为“N”(代表New)时表示要新申请一个QQ号,后面是新帐户的号码和密码;命令符为“L”(代表Login)时表示是老帐户登陆,后面是登陆信息。QQ号码为一个不超过10位、但大于1000(据说QQ老总的号码是1001)的整数。密码为不小于6位、不超过16位、且不包含空格的字符串。

输出格式:

针对每条指令,给出相应的信息:

1)若新申请帐户成功,则输出“New: OK”;
2)若新申请的号码已经存在,则输出“ERROR: Exist”;
3)若老帐户登陆成功,则输出“Login: OK”;
4)若老帐户QQ号码不存在,则输出“ERROR: Not Exist”;
5)若老帐户密码错误,则输出“ERROR: Wrong PW”。

输入样例:

  1. 5
  2. L 1234567890 myQQ@qq.com
  3. N 1234567890 myQQ@qq.com
  4. N 1234567890 myQQ@qq.com
  5. L 1234567890 myQQ@qq
  6. L 1234567890 myQQ@qq.com

输出样例:

  1. ERROR: Not Exist
  2. New: OK
  3. ERROR: Exist
  4. ERROR: Wrong PW
  5. Login: OK
  6.  
  7. 先附上使用map的代码
  1. #include <iostream>
  2. #include <map>
  3. using namespace std;
  4. map<string,string> m;
  5. int main()
  6. {
  7. int N;
  8. cin>>N;
  9. for(int i=;i<=N;++i){
  10. string QQ,mi;
  11. char ca[];
  12. cin>>ca>>QQ>>mi;
  13. if(ca[]=='L'){
  14. if(m[QQ].length()<=) {
  15. cout<<"ERROR: Not Exist\n";
  16. continue;
  17. }
  18. if(m[QQ]==mi) cout<<"Login: OK\n";
  19. else cout<<"ERROR: Wrong PW\n";
  20. }
  21. else{
  22. if(m[QQ].length()<=) {
  23. m[QQ]=mi;cout<<"New: OK\n";
  24. }
  25. else cout<<"ERROR: Exist\n";
  26. }
  27. }
  28. return ;
  29. }

下面来分享一下我的想法

QQ号最大9位数,数组开不了这么大,但是题目表示最多只会创建1e5个号码,为了实现快速查询,我们对QQ号进行哈希

先定义存储QQ号的结构体(QQ是QQ号码,mi是密码,r是指向右边的指针,下面会用到)

  1. struct node{
  2. ll QQ;
  3. string mi;
  4. node* r;
  5. };

散列函数我选择除留余数法 ,1到1e5中最大的质数为99991,令mod=99991

那么hash函数就写好了

  1. int gethash(long long int num)
  2. {
  3. return num%mod;
  4. }

接下来就要处理冲突问题了,我选择链地址法

假如多个QQ号的hash值都为key,那就把他们都放在head【key】的链表中

举个栗子

假如我创了2个QQ号,一个是99991,一个是99991*2=199982,这两个QQ号hash出来的key都是0

先开一个辅助指针数组head[100010],head[i]表示key为i的第一个节点地址(间接获得QQ号信息)

当创建QQ号是99991的时候

发现head[0]为NULL,直接new一个节点p,赋值好相关信息,令head[0]=p;

当创建QQ号是199982的时候

发现head[0]有值了,那么创立一个临时指针q=head[0]

一直令q=q->r,往右边找,如果途中找到了一个QQ号和准备创建的QQ号一样,说明QQ号存在,进行一些操作

如果到q->r为NULL的时候还没找到一个QQ号和准备创建的QQ号一样时,说明这个QQ号可以用

new一个节点p,赋值,令q->r=p(链表后插),输出创建成功

登陆的话就很简单了,只需要在对应的链表中跑,每一条链表的元素个数都不会很多,所以不会超时

图示:

AC代码:

  1. #include <iostream>
  2. #include <string.h>
  3. #define ll long long int
  4. using namespace std;
  5. const int mod = ;
  6. struct node{
  7. ll QQ;//QQ号
  8. string mi;//QQ密码
  9. node* r;//该节点右边的节点地址
  10. };
  11. node *head[];//链表头
  12. int gethash(ll num)//hash函数
  13. {
  14. return num%mod;
  15. }
  16. void login(ll QQ,string mi)
  17. {//登陆函数
  18. int key = gethash(QQ),flag_qq=;//获取散列地址key
  19. if(head[key]==NULL) {//key的链表是空的,里面没有元素,QQ号不存在
  20. cout<<"ERROR: Not Exist\n";
  21. return ;
  22. }
  23. node* now=head[key];
  24. while(now!=NULL)
  25. {//遍历key的链表
  26. if(now->QQ==QQ) {
  27. flag_qq=;
  28. if(now->mi == mi) cout<<"Login: OK\n";//string类可以进行==比较
  29. else cout<<"ERROR: Wrong PW\n";
  30. break;
  31. }
  32. now=now->r;
  33. }
  34. if(flag_qq==) cout<<"ERROR: Not Exist\n";//while循环正常退出,说明找不到这个QQ号
  35. }
  36. void create(ll QQ,string mi)
  37. {//创建QQ号
  38. int key = gethash(QQ),flag=;
  39. node *p = new node;
  40. p->QQ=QQ;p->mi=mi;p->r=NULL;//创建空间存QQ信息
  41. if(head[key]==NULL){//key的链表是空,那这个节点就是链表头了
  42. head[key]=p;
  43. cout<<"New: OK\n";
  44. }
  45. else{
  46. node *q=head[key];
  47. if(q->QQ==QQ) flag=;//打补丁 特判
  48. while(q->r!=NULL){//一直走到key链表的尽头,进行尾插
  49. if(q->QQ==QQ) {
  50. flag=;
  51. break;
  52. }
  53. q=q->r;
  54. }
  55. if(q->QQ==QQ) flag=;//打补丁 特判
  56. if(!flag) {
  57. q->r=p;
  58. cout<<"New: OK\n";
  59. }
  60. else cout<<"ERROR: Exist\n";
  61. }
  62. }
  63. int main()
  64. {
  65. int N;
  66. cin>>N;
  67. for(int i=;i<=N;++i){
  68. char str[];
  69. ll QQ;
  70. string mi;
  71. cin>>str>>QQ>>mi;
  72. if(str[]=='L'){
  73. login(QQ,mi);
  74. }
  75. else {
  76. create(QQ,mi);
  77. }
  78. }
  79. return ;
  80. }

九、自我总结

  上次的目标算是达到了吧,理解状压DP,感觉自己能理解它说啥,但是做题的时候不能熟练运用。

  下次的目标:好好复习期末考试,恶补电子电路和高数

  暑假集训加油!

第7章学习小结 不使用STL-map过实践题:QQ帐户的申请与登陆的更多相关文章

  1. 第4章学习小结_串(BF&KMP算法)、数组(三元组)

    这一章学习之后,我想对串这个部分写一下我的总结体会. 串也有顺序和链式两种存储结构,但大多采用顺序存储结构比较方便.字符串定义可以用字符数组比如:char c[10];也可以用C++中定义一个字符串s ...

  2. 20181117-python第二章学习小结-part2

    浮点型补充: 有限小数与无限循环小数,不包括无理数! 小数点后面的数据运算太复杂,精确度不及整数! 尽量使用科学计数表示小数 列表学习(语法) 创建:[] list = []  #创建空表 list ...

  3. 20181115 python-第一章学习小结part4

    python第一章 流程控制 单分枝任务 If  条件: 满足条件执行动作 注意if下面的缩进,建议直接使用tab键,4个空格太难输入. 双分枝任务 If  条件: 满足条件执行动作 else: 条件 ...

  4. 20181115 python-第一章学习小结part3

    第一章,基本数据类型-------仅学三种,字符型,数字型,布尔型 仅学三种数据类型: 字符型,加了引号的都可以被认为是字符串,字符串可以拼接 数字型,int,float,long三种,可以进行运算 ...

  5. 20181117-python第二章学习小结-part1

    什么是二进制,十进制如何转化成二进制. 在python上可使用简单的函数进行转化,bin() 数据量的基本关系: 1bit  就是0/1的一个单位 1bytes = 8bit    #1个字节,就是一 ...

  6. 20181115 python-第一章学习小结part2

    Python基本知识 变量,用来存储中间计算结果,在后面可进行调用被使用的东西,叫做变量. 变量的命名规则: 字母,数字,下划线组合 不能用数字开头 常见的关键字不能用啊 常量,不会变的量,称作常量. ...

  7. 20181115 python-第一章学习小结part1

    知识点回顾: 什么是编程: 写代码,让计算机执行任务 编程语言的分类与特性: 1.机器语言,即二进制语言,最帖近于机器底层,可以由计算机直接执行,故速度最快,但不适合开发. 2.汇编语言,直接将二进制 ...

  8. STL学习小结

    STL就是Standard Template Library,标准模板库.这可能是一个历史上最令人兴奋的工具的最无聊的术语.从根本上说,STL是一些"容器"的集合,这些" ...

  9. react学习小结(生命周期- 实例化时期 - 存在期- 销毁时期)

    react学习小结   本文是我学习react的阶段性小结,如果看官你是react资深玩家,那么还请就此打住移步他处,如果你想给一些建议和指导,那么还请轻拍~ 目前团队内对react的使用非常普遍,之 ...

随机推荐

  1. (6)打造简单OS-内存分页

    好长时间没有更新了,最近比较忙...... 内存分页可以放在C代码中,这样比较方便编写!即loader执行完后进入kernel_main函数之后在分配内存分页! 一.地址 讲到内存必然要讲到计算机中经 ...

  2. P3986 斐波那契数列——数学(EXGCD)

    https://www.luogu.org/problem/P3986 很久很久以前,我好像写过exgcd,但是我已经忘了: 洛谷上搜EXGCD搜不到,要搜(扩展欧几里得) 这道题就是ax+by=k, ...

  3. 有没有一个工具可以帮助查找python的bug和进行静态的代码分析?

    答:PyChecker是一个python代码的静态分析工具,它可以帮助查找python代码的bug, 会对代码的复杂度和格式提出警告 Pylint是另外一个工具可以进行codingstandard检查

  4. python math.asin

    import mathmath.asin(x) x : -1 到 1 之间的数值.如果 x 是大于 1,会产生一个错误. #!/usr/bin/pythonimport math print &quo ...

  5. sql 查出相同的记录 并把相同记录 显示在一起

    select c.workunit unitname,a.positionid,a.positiontype,a.isfirst,a.mastersort,a.directoraudit, c.wri ...

  6. android studio3.4打jar包

    第一步在build.gradle文件里的android{}里面加入下面内容 //生成jar包 task makeJar(type:Copy) { delete 'build/outputs/netwo ...

  7. cannot load from mysql.proc. the table is probably corrupted 解决办法

    执行以下命令:mysql_upgrade -u root -p 密码 mysql5.5及5.5以上的版本开始,mysql数据库中proc表中的comment字段的列属性已经由char(64)改为tex ...

  8. ubuntu dnsmasq

    /var/run/NetworkManager/resolv.conf 而你真实的dns服务器地址,是被这个服务管理维护着的/ local process -> local dnsmasq -& ...

  9. 如何准备算法工程师面试,斩获一线互联网公司机器学习岗offer?

    原文:https://zhuanlan.zhihu.com/p/76827460?utm_source=wechat_session&utm_medium=social&utm_oi= ...

  10. 简易的CRM系统案例之Struts2+JSP+MySQL版本

    对简易的CRM系统案例之Servlet+Jsp+MySQL版本改进 Servlet优化为Struts2 学习 <?xml version="1.0" encoding=&qu ...