堆(插入刪除)
阿新 • • 發佈:2017-10-22
bool 裏的 輸入 default main system heap move parent
用堆實現優先級隊列,插入和刪除都很快o(logN)
編程語言中的內存堆與這裏的數據結構是不一樣的
堆:一種樹(特殊的二叉樹)
特點:它是完全二叉樹,除了樹的最後一層節點不需要是滿,其他的每一層從左到右都完全是滿的。
它常常是用一個數組實現
堆中的每一個節點都滿足堆的條件,父節點的關鍵字要大於所有子節點。
堆是弱序(遍歷不適合)
插入:獲取一個節點,放入完全二叉樹中。與其父節點作比較,替換(完成父節點的關鍵字要大於子節點)
刪除:刪除頂端節點,將最後一個葉子節點賦值為頂點節點。然後移動 完成父節點的關鍵字要大於子節點。
改變節點優先級:將該節點的值更換。然後將它放在合適的位置(完成父節點的關鍵字要大於子節點)
(父節點的關鍵字要大於所有子節點,即三個點之間選取最大的與臨時父節點替換)
public class Node { private int iData;//既是關鍵字,又是數值 public Node(int key) {//初始化 iData=key; } public int getKey() {//訪問關鍵字 return iData; } public void setKey(int id) {//改變關鍵字 iData=id; } }
//建立堆 public class Heap { private Node[] heapArray;//存儲節點的數組private int maxSize;//總大小 private int currentSize;//當前堆的大小 public Heap(int mx) { maxSize=mx;//初始化總大小 currentSize=0;//初始化當前數據大小0 heapArray=new Node[maxSize]; } //判斷是否為空 public boolean isEmpty() { return currentSize==0; } //增加(判斷為滿,則不能新增) publicboolean insert(int key) { if(currentSize==maxSize) return false; Node newNode=new Node(key);//建立key節點 heapArray[currentSize]=newNode;//將key節點插入數組的最末 //(向上調整)完成堆的規則(父節點大於子節點) trickleUP(currentSize); currentSize++;//增加成功,數量加1 return true; } //向上調整(只需要跟父節點做比較就行了,因為開始的時候父節點就是最大值) public void trickleUP(int index) { //取父節點 int parent=(index-1)/2; //比較,交換 Node bottom=heapArray[index]; while(index>0 && heapArray[parent].getKey()<bottom.getKey()) {//尋找需要替換的位置 heapArray[index]=heapArray[parent]; index=parent; parent=(parent-1)/2; } heapArray[index]=bottom; } //刪除(刪除根,將最後一個數據項移到根上,然後做調整) public Node remove() { Node root=heapArray[0]; heapArray[0]=heapArray[--currentSize];//將最後一個數據項移到根上 //向下調整 trickleDown(0); return root; } //向下調整 public void trickleDown(int index) { int largeChild;//記錄大的子節點 Node top=heapArray[index]; while(index<currentSize/2) {//指針到了最後一層才停止循環 int leftChild=2*index+1;//左子節點 int rightChile=leftChild+1; //右子節點 if(rightChile<currentSize && heapArray[leftChild].getKey()<heapArray[rightChile].getKey())//有右子節點 largeChild=rightChile; else largeChild=leftChild; if(top.getKey()>=heapArray[largeChild].getKey()) break; heapArray[index]=heapArray[largeChild];//將大的關鍵字調整 index=largeChild; } //最後定位Node top=heapArray[index] heapArray[index]=top; } //更改關鍵字 public boolean change(int index, int newValue) { if(index<0 || index >=currentSize) return false;//非正常索引 int oldValue=heapArray[index].getKey(); heapArray[index].setKey(newValue);//改變數據項 //如果新的數據項大於舊的數據項,就向上調整。如果小於舊的數據項,就向下調整 if(oldValue<newValue) { trickleUP(index); }else trickleDown(index); return true; } //顯示堆 public void displayHeap() { //以數組的方式 System.out.println("堆數組"); for(int m=0;m<currentSize;m++) if(heapArray[m]!=null) System.out.print(heapArray[m].getKey()+" "); else System.out.print("-- "); System.out.println(); //以樹狀的形式 int nBlanks=32;//控制空格 int itemsPerRow=1;//當前層的個數 int column=0;//當前層的數量 int j=0; String dots="..............................."; System.out.println(dots+dots); while(currentSize>0) { if(column==0) { for(int k=0;k<nBlanks;k++) System.out.print(‘ ‘); } System.out.print(heapArray[j].getKey()); if(++j==currentSize)//全部打印完成 break; if(++column==itemsPerRow) {//當前層打印完 nBlanks/=2; itemsPerRow*=2; column=0; System.out.println(); }else for(int k=0;k<nBlanks*2-2;k++) System.out.print(‘ ‘); } System.out.println("\n"+dots+dots); } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class Test { public static void main(String[] agrs) throws IOException{ int value,value2; Heap theHeap =new Heap(31); boolean success; theHeap.insert(70); theHeap.insert(40); theHeap.insert(50); theHeap.insert(20); theHeap.insert(60); theHeap.insert(100); theHeap.insert(80); theHeap.insert(30); theHeap.insert(10); theHeap.insert(90); while(true) { System.out.println("Enter first letter of show ,insert,remove,change:"); int choice=getChar(); switch(choice){ case ‘s‘: theHeap.displayHeap(); break; case ‘i‘: System.out.print("enter value"); value=getInt(); success=theHeap.insert(value); if(!success) System.out.println("man le"); break; case ‘r‘: if(!theHeap.isEmpty()) theHeap.remove(); else System.out.println("不能刪除"); break; case ‘c‘: System.out.println("輸入要改變的索引"); value=getInt(); System.out.println("輸入要改變的值"); value2=getInt(); success=theHeap.change(value, value2); if(!success) System.out.println("無效的索引"); break; default : System.out.println("無效的輸入"); } } } public static String getString() throws IOException{ InputStreamReader isr=new InputStreamReader(System.in); BufferedReader br=new BufferedReader(isr); return br.readLine(); } public static char getChar() throws IOException{ return getString().charAt(0); } public static int getInt() throws IOException{ return Integer.parseInt(getString()); } }
堆(插入刪除)