【Heap】Data Structure|Detailed Analysis|Perfect Interpretation|Heap Sorting|Simulation Heap

1. The nature and characteristics of the heap

1. Heap data structure

We think of heap as a complete binary tree data structure. When using this data structure, we will use some properties of binary trees. These properties require our emphatic understanding and application

The parent-child relationship of the binary tree
Let a node be u: 2 * u is his left child node, 2 * u+ 1 is his right child node Let a node be u: u /
2 is his father node

insert image description here

2. Heap storage structure

Although the heap in the data structure is a non-linear data structure, its storage structure is an absolute linear storage structure. We use a pointer cnt to complete the data input and output operations of the heap structure.

3. The characteristics of the heap

The h[1] of the heap is always the minimum value, because the push-in and push-out operations of the heap

2. Heap operation and code implementation

1. Basic operation of the heap

The heap consists of two basic operations, down and up operations, which involve the basic construction and most operations of the heap data structure. We first start with the down operation. The down operation is to compare with his son nodes every time. If they are larger than their father, they will perform an exchange operation. When the two values ​​​​are smaller than his father node, select them for comparison. The smaller one is exchanged.


void down (int u)
{
    
    
	int t = u ;
	if(2 * u  <= cnt && h[2 * u] < h[t])	t = 2 * u;
	if(2 * u + 1 <= cnt && h[2 * u + 1] < h [t]) t = 2 *  u + 1 ;
	
}

After completing this step of exchange judgment, we first judge whether he wants to exchange. If he wants to perform exchange operation, we will perform exchange operation, and complete the remaining down operation again after the exchange is completed .

if(u ! = t)
{
    
    
	swap(h[t] , h[u] );
	down(t) ;
}

To summarize this operation

void down(int u)
{
    
    
	int t = u ;
	if( 2 * u <= cnt && h[ 2 * u] < h[t])	t = 2 * u;
	if(2 * u + 1 <= cnt && h[2 * u + 1] < h[t] ) t = 2 * u + 1;
	if(t != u )
	{
    
    
		swap(h[t],h[u]);
		down(t) ;
	}
}

After completing this simple down operation, let’s take a look at the simple up operation. The up operation is actually to look at the relationship between the father’s node and its size. When the father is older, exchange and go up again . Let’s look at the code implementation below.

void up (int u )
{
    
    
	while(u / 2 > 0 && h[u / 2] > h[u])
	{
    
    
		swap(h[u / 2],h[u]);
		u = u / 2;
	}
}

2. Heap operation

2.1 Heap initialization operation

We use up and down to complete the initialization operation. First of all, we know that the heap is a complete binary tree. Using the properties of this complete binary tree, we can know that the minimum value of the heap is at the top. When we use down to complete this operation, we are Complete this operation from bottom to top, and the last line does not need to perform this operation.
insert image description hereWhen we use the up operation, it is not easy to control. Generally, we do not use the up operation for initialization.

2.2 Heap sorting (integrated operation)

The heap traverses the number h[1] every time , and pops it up. After popping up, we assign the last element to h[1] and then perform down(1) operation.

#include <iostream>
using namespace std ;

const int N = 100010 ;

int h[N] , cnt ;

void down (int u )
{
    
    
	int t = u ;
	if(2 * u <= cnt && h[2 * u] < h[t]) t = 2 * u;
	if(2 * u  + 1 <= cnt && h[2 * u + 1 ] < h[t]) t = 2 * u + 1;
	if(t != u)
	{
    
    
		swap(h[u], h [t]);
		down(t);
	}

}

int main ()
{
    
    
	int n ,m;
	cin >> n >> m;
	cnt = n ;
	for(int i = 1 ; i <= n ; i ++)
		cin >> h[i] ;
	for(int i = n / 2 ; i ; i --)
		down(i) ;
	for(int i = 0 ; i < m ; i ++ )
	{
    
    
		int x = h[1];
		h[1] = h[ cnt -- ];
		down(1) ;
		cout << x << " ";
	}
	return 0 ;
}

The above operations are perfect, but there are still some areas for improvement. Although this heap can quickly respond to the minimum value, we still have no way to insert the kth value. Of course, we can unify the following Heap simulation to modify the swap_1 function.

3. Advanced simulation of the heap

In the advanced operation of the heap, since we want to perform operations related to the kth operation of the heap, we open two pointers— mutual pointers , ph[N] , hp[N] .
insert image description hereFirst of all, we need to change the swap function in order to find out this relevant value in up and down .

void swap_1(int u ,int v)
{
    
    
	swap(h[u],h[v]);
	swap(hp[u],hp[v]);
	swap(ph[hp[u]],ph[hp[v]]);
}

The change of the remaining operation is that when initializing the assignment, we need to complete their assignment operation for both pointers, the position pointed to by the number of ph[N] inserted, m++, cnt++ can complete this assignment operation very well , the same hp[N] is a complete negation operation

#include <iostream>
using namespace std ;

const int N = 100010 ;

int h[N] , cnt ;
int hp[N], ph[N];

void swap_1(int u ,int v)
{
    
    
	swap(h[u],h[v]);
	swap(hp[u],hp[v]);
	swap(ph[hp[u]],ph[hp[v]]);
}
void down (int u )
{
    
    
	int t = u ;
	if(2 * u <= cnt && h[2 * u] < h[t]) t = 2 * u;
	if(2 * u  + 1 <= cnt && h[2 * u + 1 ] < h[t]) t = 2 * u + 1;
	if(t != u)
	{
    
    
		swap_1(u, t);
		down(t);
	}

}
void up (int  u)
{
    
    
	while (u / 2 and h[u / 2 ] > h[u])
	{
    
    
		swap_1(u,u / 2);
		u = u / 2;
	}
}



int main ()
{
    
    
	int n ;
	cin >> n ;
	int m = 1 ;
	while ( n -- )
	{
    
    
	    string str ;
	    cin >> str ;
	    if(str == "I")
	    //I 操作是一个标准的插入操作;
	    {
    
    
	        int x ;
	        cin >> x ;
	        h[++ cnt ] = x ;
	        //基础的的赋值操作
	        ph[m] = cnt ; hp[cnt] = m ++ ;
	        
	        //常规的:ph[N].hp[N[赋值操作;
	        up(cnt);
	    }
	    else if(str == "PM")
	    //返回最小值
	        cout << h[1] <<endl;
	    else if(str == "DM")
	    //删除最小值
            {
    
    
                swap_1(1,cnt);
                cnt -- ;
                //删除
                down(1) ;
                //规整操作;
            }
        else if(str == "D")
        //删除第k个插入的数
            {
    
    
                int k ;
                cin >> k;
                k = ph[k] ;
                swap_1(cnt -- , k);
                down (k) ;
                up(k) ;
            }
        else 
        {
    
    
        //更换第k个插入的数值为x 
            int k , x;
            cin >> k >> x;
            k = ph[k];
            h[k] = x;
            up(k);
            down(k);
        }
	}
	return 0 ;
}

Guess you like

Origin blog.csdn.net/wen030803/article/details/131680536