今天看到一道面試題,
一個最小堆,也是完全二叉樹,用按層遍歷數組表示。
1. 求節點a[n]的子節點的訪問方式
2. 插入一節點的程序void add_element(int *a,int size,int val);
3. 刪除最小節點的程序。
剛看到的時候覺得挺難的,沒有什麼思路,原因在於對最小堆的完全二叉樹不瞭解,其實這個二叉樹和堆排序時建立的二叉樹是一樣的。
1、按照數組下標,下標爲n的節點,它的子結點下標爲2*n+1和2*n+2;
2、插入節點時,先插入到最後,然後再調整堆。
3、刪除最小節點即刪除根節點,先將根節點和最後一個節點交換,再調整堆。
- #include "stdafx.h"
- #include<iostream>
- using namespace std;
- //往最小堆中插入元素,先插在數組的最後,然後類似於插入排序找到合適位置。
- void MinHeapAdd(int *a,int n,int number)
- {
- a[n]=number;
- int i=n;
- int j=(i-1)/2;
- int tmp=a[i];
- while(j>=0)
- {
- if(a[j]<=tmp)
- break;
- else
- {
- a[i]=a[j];
- i=j;
- j=(i-1)/2;
- }
- }
- a[i]=tmp;
- }
- //從第m個開始調整,n爲結點總數 類似於插入排序
- void MinHeapFixDown(int *a,int m,int n)
- {
- int i=m;
- int j=2*i+1;
- int tmp=a[i];
- while(j<n)
- {
- if(j+1<n&&a[j]>a[j+1])
- j++;
- if(a[j]>=tmp)
- break;
- else
- {
- a[i]=a[j];
- i=j;
- j=2*i+1;
- }
- }
- a[i]=tmp;
- }
- //刪除最小節點
- void MinHeapDelete(int *a,int n)
- {
- a[0]=a[n-1];
- MinHeapFixDown(a,0,n-1);
- }
- //初始建堆
- void MakeMinHeap(int *a,int n)
- {
- for(int i=n/2-1;i>=0;i--)//注意
- MinHeapFixDown(a,i,n);
- }
- //堆排序
- void HeapSort(int *a,int n)
- {
- MakeMinHeap(a,n);
- for(int i=n-1;i>=1;i--)
- {
- int tmp=a[0];a[0]=a[i];a[i]=tmp;
- MinHeapFixDown(a,0,i);
- }
- }
- void main()
- {
- int a[10]={36,30,18,40,32,45,22,50};
- HeapSort(a,8);
- for(int i=0;i<8;i++)
- cout<<a[i]<<" ";
- cout<<endl;
- int aa[10]={36,30,18,40,32,45,22,50};
- MakeMinHeap(aa,8);
- for(int i=0;i<8;i++)
- cout<<aa[i]<<" ";
- cout<<endl;
- MinHeapAdd(aa,8,35);
- for(int i=0;i<9;i++)
- cout<<aa[i]<<" ";
- cout<<endl;
- MinHeapDelete(aa,9);
- for(int i=0;i<8;i++)
- cout<<aa[i]<<" ";
- cout<<endl;
- }