数据结构面试总结

本文主要总结了数据结构中的核心概念,包括红黑树、二叉树、Vector和哈希表。红黑树保证了插入、删除、查找的效率为O(logn);二叉树的遍历包括先序、中序、后序非递归实现;Vector在扩容时可能导致迭代器失效;哈希表则讨论了哈希函数、冲突解决策略和一致性哈希算法。
摘要由CSDN通过智能技术生成

数据结构

持续更新,或有缺陷

红黑树

  1. 每个节点要么是红色,要么是黑色。
  2. 根节点是黑色的。
  3. 叶节点是黑色的。
  4. 如果有一个节点是红色的,那么它的两个儿子节点都是黑色的。
  5. 任意节点,到叶子节点尾端NIL所经过的黑色节点的个数相同。
  6. 红黑树插入、删除、查找的效率都是 O ( l o g n ) O(logn) O(logn)

二叉树

二叉树的定义:二叉树是有限个点的集合,它要么是空集,要么是由根节点和两棵互不相交的二叉树组成,其中一棵叫根的左子树,另外一棵叫根的右子树。

  1. 二叉树第 i i i层的节点最多为 2 i − 1 2^{i-1} 2i1

  2. 高度为 k k k的二叉树,其节点总数最多为 2 k − 1 2^k-1 2k1

  3. 满二叉树:深度为 k k k且有 2 k − 1 2^k-1 2k1个节点的二叉树称为满二叉树

  4. 平衡二叉树:平衡二叉树也称 A V L AVL AVL树,它要么是空树,要么满足:

    1. 由两棵平衡二叉树组成
    2. 左子树和右子树深度之差的绝对值不超过1
  5. 二叉树的遍历

    1. 先序遍历的非递归实现
    void preOrderNonRecursive(node* root) {
    	stack<node*> Stack;
    	node* p = root;
    
    	while (!Stack.empty() || p != nullptr) {
            // 遍历左子树,依次打印
    		while (p != nullptr) {
    			cout << p->val << " ";
    			Stack.push(p);
    			p = p->left;
    		}
    
            // 如果栈不为空,弹出栈顶元素,遍历右子树
    		if (!Stack.empty()) {
    			p = Stack.top();
    			Stack.pop();
    			p = p->right;
    		}
    	}
    	cout << endl;
    }
  1. 中序遍历非递归实现
      void inOrderNonRecursive(node* root) {
      	stack<node*> Stack;
      	node* p = root;
      
      	while (p != nullptr || !Stack.empty()) {
      		// 若跟节点不为空,则遍历左子树
              while (p != nullptr) {
      			Stack.push(p);
      			p = p->left;
      		}
      
              // 输出中间节点,然后遍历右子树
      		if (!Stack.empty()) {
      			p = Stack.top();
      			Stack.pop();
      			cout << p->val << " ";
      			p = p->right;
      		}
      	} 
      	cout << endl;
      }
  1. 后序遍历非递归实现
      void postOrderNonRecursive(node* root) {
      	stack<node*> Stack;
      	node* cur;
      	node* pre = nullptr;
      	Stack.push(root);
      
      	while (!Stack.empty()) {
      		cur = Stack.top();
              // 如果当前节点无孩子,或者孩子节点均被访问过
      		if ((cur->left == nullptr && cur->right == nullptr) ||
      			(pre != nullptr && (pre == cur->left || pre == cur->right))) {
      			cout << cur->val << " ";
      			pre = cur;
      			Stack.pop();
      		}
              // 相当于后序遍历过程
              else {
      			if (cur->right != nullptr) {
      				Stack.push(cur->right);
      			}
      			if (cur->left != nullptr) {
      				Stack.push(cur->left);
      			}
      		}
      	}
      	cout << endl;
      }

Vector

  1. size()返回的是当前元素的个数,capacity()返回的是已经分配的内存中可以容纳多少元素。
  2. gcc是1.5倍扩容,VS2013是2倍扩容,一旦引起空间的重新配置,原来的所有迭代器都会失效。
  3. Vector进行内存释放的方式是使用swap,通过swap构造的临时对象调用该swap函数,在完成swap功能后,临时对象就会被释放掉。

哈希表

  1. 哈希函数:将不同的输出值,得到特定长度的信息摘要,符合同一性和雪崩效应。
  2. 冲突解决:
    1. 链地址法
    2. 线性探测
    3. 二次探测
  3. 一致性哈希算法(consistent hashing)
    1. Hash算法的衡量标准之一是单调性(Monotonicity):如果有部分内容通过哈希分派到相应的缓冲,又有新的缓冲加入到系统中,哈希的结果应该能够保证原有已分配的内容可以被映射到新的缓冲中,而不会被映射到旧的缓冲集合中的其他缓冲区。
    2. 普通的哈希算法是对服务器的数量求模,而一致性哈希是对 2 32 2^{32} 232进行取模,首先将不同服务器的IP映射到环上不同的位置,然后再对数据进行相同的哈希,映射到换上的不同位置,然后再对每个数据,顺时针找到第一个服务器,然后与之对应,如果某一台服务器宕机,只需要修该服务器前面的节点即可,新增服务器同理,因此只需要修该一小部分的数据,不会造成过大的影响。为了解决数据倾斜的问题,引入虚拟节点的概念。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值