Data Structure Interview Summary

data structure

Continuously updated, or buggy

red-black tree

  1. Each node is either red or black.
  2. The root node is black.
  3. Leaf nodes are black.
  4. If a node is red, then both of its children are black.
  5. For any node, the number of black nodes passing through NIL at the end of the leaf node is the same.
  6. The efficiency of red-black tree insertion, deletion and search is O(logn) O(logn)O ( l o g n )

binary tree

Definition of binary tree: A binary tree is a set of finite points, which is either an empty set or consists of a root node and two disjoint binary trees, one of which is called the left subtree of the root, and the other is called the right subtree of the root. subtree.

  1. Binary tree iiThe nodes at level i are at most 2 i − 1 2^{i-1}2i1

  2. height is kkA binary tree of k with a total number of nodes at most2 k − 1 2^k-12k1

  3. Full binary tree : depth is kkk and there are2 k − 1 2^k-12kA binary tree with 1 node is called a full binary tree

  4. Balanced Binary Tree : Balanced Binary Tree is also known as AVL AVLA V L tree, which is either an empty tree or satisfies:

    1. Consists of two balanced binary trees
    2. The absolute value of the difference between the depths of the left subtree and the right subtree does not exceed 1
  5. traversal of binary tree

    1. A non-recursive implementation of preorder traversal
    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. Inorder traversal non-recursive implementation
      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. Post-order traversal non-recursive implementation
      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() returns the current number of elements, and capacity() returns how many elements can fit in the allocated memory.
  2. The expansion of gcc is 1.5 times, and the expansion of VS2013 is 2 times. Once the space is reconfigured, all the original iterators will be invalid.
  3. The way to release the memory of Vector is to use swap, and the swap function is called through the temporary object constructed by swap. After the swap function is completed, the temporary object will be released.

hash table

  1. Hash function: Combine different output values ​​to get a digest of information of a specific length, in line with identity and avalanche effects.
  2. Conflict Resolution:
    1. chain address method
    2. Linear detection
    3. Secondary detection
  3. Consistent hashing
    1. One of the measurement criteria of the Hash algorithm is Monotonicity: if some content is distributed to the corresponding buffer through hashing, and a new buffer is added to the system, the hash result should be able to guarantee the original allocated content. Can be mapped to the new buffer without being mapped to other buffers in the old set of buffers.
    2. Ordinary hashing algorithms are modulo the number of servers, while consistent hashing is 2 32 2^{32}23 2 for modulo, first map the IPs of different servers to different positions on the ring, then perform the same hash on the data, map to the different positions replaced, and then find the first for each data clockwise. If a server goes down, only the node in front of the server needs to be repaired. The same is true for adding a new server. Therefore, only a small part of the data needs to be repaired, and it will not cause excessive damage. influence. In order to solve the problem of data skew, the concept of virtual node is introduced.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324081305&siteId=291194637