data structure

Heap and Heapsort

Before talking about heap sorting, we must first talk about selection sorting. The idea of ​​heap sorting is actually the same as selection sorting.
Let’s briefly summarize the various sorting:
1. Insertion sorting, analogous to inserting a card, thinks that the previous number has been sorted, traverses to the new number, and inserts it into the position where it should be.
2. Select sort, traverse the array each time, select the largest or smallest number in the unsorted part, put the smallest or largest number at the top, and then move the rest one bit backward
3. Bubble sort, basic idea It is to sink the larger number at the bottom and the smaller number to float on top.

Heap sort is actually a stepwise selection of the largest or smallest value in an unsorted array to sort. So how is he better than selection sort, in that he uses the structural characteristics of the large top heap or the small top heap to speed up the selection.

heap structure

The heap can be abstractly understood as the structure of a binary tree, but it only needs to be stored in an array, and the value of the parent node is always greater than or equal to the value of the left and right child nodes (big top heap). Note that in the array, if the position k is the parent node, then its left and right child nodes are at 2k and 2k+1! ! ! !

How to refactor an unordered array into a heap ordered array

Check all parent nodes, that is, nums[1:length/2]when the parent node is found to be smaller than the child node, the parent and child nodes should be exchanged, that is, the parent node will sink.

void heap(vector<int> &nums,int n){
    //n表示带排列数组的长度
    //检查所有父节点,即```nums[1:length/2]```当发现父节点比子节点小的时候,要将父节点和左右子节点中较大的那个交换,即父节点下沉。
    for(int k=n/2;k>=1;k--)
        sink(nums,k,n);
    return;
}
void sink(int* nums,int parentIndex, int numsSize){
    while(2*k<=n){
        int j=2*k;
        //找到子节点较大的那个
        if(j<n && nums[j]<nums[j+1]) j++;
        //如果下沉过程中,出现父节点大于等于左右子节点则停止下沉
        if(nums[k]>=nums[j]) break;
        //将父子节点贾环,完成下沉
        swap(nums[k],nums[j]);
        //换完之后,更改父节点位置,继续下沉
        k=j;
    }
}

Correctly sort a heap sorted array

Swap the first bit of the heap-ordered array, which is the root node (maximum value), with the last bit, and then reconstruct the heap-ordered array for all but the last bit. Then continuously take out the maximum value, which is the root node.

void heapSort(vector<int>& nums){
    int n=nums.size();
    //初次堆排序
    heap(nums, n);
    //依次取出最大值
    while(n>1){
        swap(nums[1],nums[n--]);
        //重新堆排序
        sink(nums,1,n);
    }
}

priority queue

Priority queue is a variant of the queue, first in but always the largest number first out. Each time a number is added to the end of the array, and then it is continuously floated (or the above sinking algorithm until all the values ​​are in heap order), the top value can always remain the maximum value.

hash table

For data, the most important operations are search, insert, delete and so on. Because the array is stored continuously in the memory, the data can be retrieved in O(1) time through the index, while the linked list needs to be traversed due to the discontinuous storage address, and the worst takes O(n) time. But for insertion, the advantage of linked list is great.

The essence of HashTable is to store data in an array, but how can it be inserted and deleted quickly?

The idea is to use a function to map a given key to a function to get an integer, and then take the remainder of the number to the length of the array to store the data, and the result is the array subscript of the stored value. So insertion, lookup, and deletion all take close to O(1) time.

But a very important question is how to avoid hash collisions? That is, what if the mapping results are the same?

  1. The zipper method used by Java's HashMap The linked list is stored in the
    array . Once the mapped subscript is occupied, the value is attached to the end of the linked list.
    image

  2. Set up a buffer, put all those who repeat the pinyin into the buffer. When I look up a person by name, I find that I am not looking for it, so I look for it in the buffer.

  3. Re-detection is performed. Just look elsewhere. There are also many ways to detect.

    3.1 Search at the index-1, index+1 position of the index where the search position is found, index-2, index+2, and so on. This method is called linear reprobing.

    3.2 Random search around the search position index. Called random probing.

    3.3 Rehashing. That is, when there is a conflict, another mapping method is used to find it.

binary tree

traversal of binary tree

  1. preorder traversal
    def preorderTraversal(self, root):
        results = []
        self.frontIter(root, results)
        return results

    def frontIter(self, root, results):
        if root:
            results.append(root.val)
            self.frontIter(root.left, results)
            self.frontIter(root.right, results)
  1. Inorder traversal

  2. post-order traversal

  3. Hierarchical Traversal

search binary tree

Balanced Binary Tree

red-black tree

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324721738&siteId=291194637