2018秋招面试问题(十一、数据结构基础问题)

注:面试过程中整理的学习资料,如有侵权联系我即刻删除。

目录

数据结构中链表和数组的异同?

队列的数据结构,以及循环(环形)队列如何实现

队列和栈的使用场景

数据结构中数组、链表、堆栈有些什么区别?

如何实现哈希表?向后寻址好吗?

Hashtable

hashtabe和hashmap的不同

为什么hashmap是线程不安全的?为什么hashtabe是线程安全的?

STL之认识hash_set和hash_map

哈希表的数据检索

哈希表是如何存字符串的?

什么时候用哈希map,什么时候用map?

XML中的节点是什么数据结构


数据结构中链表和数组的异同?

数组的元素在内存中是连续存放的,我们可以通过下标快速访问到某个元素,而如果要对数组进行增加或者删除元素,就要移动大量的元素,插入删除的效率低。并且数组的大小是固定的,不能动态扩展。可能浪费内存。

链表的元素在内存中是不连续的,由结点组成,每个结点都包含一个指针域(存储下一个结点的指针)一个数据域。访问链表元素需要从第一个结点开始,遍历找到该结点元素,查找效率低,但是增加和删除元素就很方便,只需要修改结点指针的指向,链表内存利用率很高,大小不固定,扩展很灵活。

<在a、c节点中插入b结点:a->next = b; b->next = c;如果没给出c,那就是b->next = a->next; a->next = b;

删除a的下一个结点:a->next = a->next->next;

delete item;>

所以如果是要快速访问元素,那就使用数组,如果是需要经常删除增加元素,那就使用链表。

队列的数据结构,以及循环(环形)队列如何实现

入队列的时候是队头保持不变,队尾++;

出队列的时候是队尾保持不变,队头++;

循环(环形)队列只要在插入数据的时候对队列容量取余就好了,代表队尾的下一个指向了队头。

队列和栈的使用场景

栈是先进后出,队列是先进先出。

<从左到右打印二叉树的结点是用队列。>

队列:计算机各种资源的管理、消息缓冲器的管理。

栈:匹配表达式的括号(遇到左括号就压栈,遇到右括号就出栈)

以及函数的递归实现。

数据结构中数组、链表、堆栈有些什么区别?

数组是一块连续的内存空间,数据个数是在分配内存时就确定了的。数组的访问的时间复杂度是O(1),查找的时间复杂度是O(N),删除和插入的时间复杂度也是O(N)。

链表是非连续的内存单元,通过指针将各个单元连在一起,链表不需要提前分配固定大小的存储空间,当需要分配内存的时候分配一块内存并把这块内存插入链表中。链表的查找和访问数据的时间复杂度都是O(N),插入和删除数据的时间复杂度都是O(1)。

堆是树形数据结构,每个节点都有一个值,可以说就是一棵树。有二叉树和K叉树堆。堆分为大顶堆和小顶堆<大顶堆的子树也都是大顶堆>。根节点的两个子树也是堆。我们平时常用的堆都是二叉堆,是一个完全二叉树。应用场景包括堆排序、优先队列。

栈是先进后出的结构,对栈的数据操作都只能在顶部,只可以查看、插入、删除栈顶部的数据。(push\pop\top)

队列是先入先出的结构,队列只允许在队头删除数据,在队尾增加数据,但是都可以查看队头队尾的数据。

如何实现哈希表?向后寻址好吗?

<哈希表和数组的查找都是O(1),哈希和数组一样都很耗空间>

哈希表解决冲突有几种方法:开放定址法、链地址法、再哈希法。平时主要用开放定址法

开放定址法的优缺点:

缺点:a存储记录的数目不能超过桶数组的长度,如果超过了就需要扩容,而扩容会导致时间成本飙升。b使用探测序列,有可能计算key的时间成本很高。c删除记录时,比较麻烦,比如需要删除记录A,记录B是在A之后插入桶数组的,但是和记录A有冲突,是通过探测序列再次跳转找到的地址,所以如果直接删除A,A的位置变为空槽,而空槽是查询记录失败的终止条件,这样会导致记录B在A的位置重新插入数据前不可见,所以不能直接删除A,而是设置删除标记。这就需要额外的空间和操作。

优点:a记录更容易进行序列化操作。b如果预知记录总数,可以创建完美哈希函数,此时的效率很高。

链地址法:

Hashtable

 Hashtable是基于哈希表实现的,每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,会自动增长。Hashtable不允许key和value是NULL的。

Hashtable的put和get方法。

put方法:计算key的hash值,根据hash值获得key在table数组中的索引位置,然后迭代该key处的Entry链表(我们暂且理解为链表),若该链表中存在一个这个的key对象,那么就直接替换其value值即可,否则在将该key-value节点插入该index索引位置处。插入元素时会首先进行容量校验,如果容量已经达到了阈值,hashtable会进行扩容处理rehash()。得到key的hash值主要是通过hashcode函数值与hashseed位与得到的。hashSeed,这是一个实例有关的随机值,主要用来解决哈希冲突。

get方法:处理过程就是计算key的hash值,判断在table数组中的索引位置,然后迭代链表,匹配直到找到相对应key的value,若没有找到返回null。

hashtabe和hashmap的不同

hashtable和hashmap都是STL容器。都是基于哈希表结构的,都是用链地址法来处理的冲突。

  1. hashtable不允许key和value为null,而hashmap可以。
  2. 遍历的话两个都可以用迭代器,只是hashtable还可以使用Enumeration方法。
  3. 在计算hash值时,hashtable用的key的hashcode()来得到,hashmap则是重新计算hash值。

hashtable是线程安全的,hashmap是线程不安全的。

为什么hashmap是线程不安全的?为什么hashtabe是线程安全的?

hashmap不安全:主要是addEntry()函数,多个线程都可以得到当前哈希表位置的头结点,并修改头结点。这样别的线程就会覆盖之前线程的操作。

hashtable安全:是加了锁的,synchronized。

STL之认识hash_set和hash_map

hash_set是限制了功能的hash_map,底层是由hash_map来实现的。对于重复的数据不会再插入。

哈希表的数据检索

哈希表是根据Key---value来直接进行访问的数据结构,以加快查找的速度。是一种寻址容易,插入和删除也容易的数据结构。

哈希表的数据检索,是通过哈希函数。计算出数据所存放的哈希地址。即算出数据在哪个桶的单链中,然后对单链中的每一个数据进行比較,检索出所要的数据。为了使每一个桶中的元素尽可能地少,使用大质数作为表长,并且使用表长作为求余运算的模。

哈希表有多种实现方法,以下是拉链法

左边是个数组,数组中都是指针,指向一个链表的头,我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。

哈希表是如何存字符串的?

首先将字符串通过哈希算法hash(key)算出对应的哈希值,再取一个大质数取余%,来得到这个字符串所在的key值对应。

哈希算法有非常多,如果是单字符,就可以直接用字符所代表的ASIC码来作为key,字符串abcde可以用97*1+98*E^1+99*E^2+100*E^3+101*E^4来表示这个字符串的key。

什么时候用哈希map,什么时候用map?

两个都是map容器,不同的是key的结构不同。

map的key是红黑树结构(二叉平衡排序树),哈希map的key是哈希表的结构。Hash_map检索出来的元素是无序的,map用迭代器遍历出来的元素是有序的。树结构的查找是O(nlog2n),哈希表结构的查找很快,是O(1)。但是树结构比较有利于插入和删除,所以删除和插入比较多的时候,用map比较好;数据量很大,查询频繁的时候用哈希map比较好。

XML中的节点是什么数据结构

是链表和树,next和pre指针组成链表,children和parent指针组成树。

XML文档的操作其根本原理就是在节点之间移动、查询节点的各项信息,并进行增加、删除、修改等操作。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值