1. 程式人生 > >實現最大堆的插入和刪除!

實現最大堆的插入和刪除!

[java] view plain copy print?
import java.util.*;   
   
/** 
 *實現的最大堆的插入和刪除操作 
 * @author Arthur 
 */   
public class Heap {   
     /** 
     * 刪除堆中位置是index處的值 
     * 操作原理是:當刪除節點的數值時,原來的位置就會出現一個孔 
     * 填充這個孔的方法就是,把最後的葉子的值賦給該孔,最後把該葉子刪除 
     * @param heap 一個最大堆 
     */   
    public static void delete(List<Integer> heap,int index) {   
        //把最後的一個葉子的數值賦值給index位置   
        heap.set(index, heap.get(heap.size() - 1));   
        //下沉操作   
        //heapDown2(heap, index);   
        heapDown(heap, index); //節點下沉  
        //把最後一個位置的數字刪除   
        heap.remove(heap.size() - 1);   
    }   
   
   
    /**  
     * 節點下沉遞迴實現 
     * 刪除一個堆中一個數據的時候,根據堆的性質,應該把相應的位置下移,才能保持住堆性質不變 
     * @param heap 保持最大堆元素的陣列 
     * @param index 被刪除的那個節點的位置 
     */   
    public static void heapDown(List<Integer> heap, int index) {   
        //因為第一個位置儲存的是空值,不在考慮之內   
        int n = heap.size() - 2;   
   
        //記錄最大的那個兒子節點的位置   
        int child = -1;   
   
        //2*index>n說明該節點沒有左右兒子節點了,那麼就返回   
        if (2 * index > n) {   
            return;   
        } //如果左右兒子都存在   
        else if (2 * index < n) {   
   
            //定義左兒子節點   
            child = 2 * index;   
            //如果左兒子小於右兒子的數值,取右兒子的下標   
            if ((Integer) heap.get(child) < (Integer) heap.get(child + 1)) {   
                child++;   
            }   
   
        }//如果只有一個兒子(左兒子節點)   
        else if (2 * index == n) {   
            child = 2 * index;   
        }   
   
        if ((Integer) heap.get(child) > (Integer) heap.get(index)) {   
            //交換堆中的child,和index位置的值   
            swap(heap, child, index);   
   
            //完成交換後遞迴呼叫,繼續下降   
            heapDown(heap, child);   
        }   
    }   
   
    //非遞迴實現   
    public static void heapDown2(List<Integer> heap, int index) {   
        int child = 0;//儲存左兒子的位置   
   
        int temp = (Integer) heap.get(index);   
        int n = heap.size() - 2;   
        //如果有兒子的話   
        for (; 2 * index <= n; index = child) {   
            //獲取左兒子的位置   
            child = 2 * index;   
            //如果只有左兒子   
            if (child == n) {   
                child = 2 * index;   
            } //如果右兒子比左兒子的數值大   
            else if ((Integer) heap.get(child) < (Integer) heap.get(child + 1)) {   
                child++;   
            }   
   
            //如果數值最大的兒子比temp的值大   
            if ((Integer) heap.get(child) >temp) {   
                //交換堆中的child,和index位置的值   
                swap(heap, child, index);   
            } else {   
                break;   
            }   
        }   
    }   
   
      
     //列印連結串列   
    public static void print(List<Integer> list) {   
        for (int i = 1; i < list.size(); i++) {   
            System.out.print(list.get(i) + " ");   
        }   
        System.out.println();  
    }   
   
    //把堆中的a,b位置的值互換   
    public static void swap(List<Integer> heap, int a, int b) {   
        //臨時儲存child位置的值   
        int temp = (Integer) heap.get(a);   
   
        //把index的值賦給child的位置   
        heap.set(a, heap.get(b));   
   
        //把原來的child位置的數值賦值給index位置   
        heap.set(b, temp);   
    }   
   
    //向最大堆中插入元素   
    public static void insert(List<Integer> heap, int value) {   
           //在陣列的尾部新增要插入的元素  
        if(heap.size()==0)  
          heap.add(0);//陣列下標為0的位置不放元素  
        heap.add(value);   
        //開始上升操作   
       // heapUp2(heap, heap.size() - 1);   
        heapUp(heap, heap.size() - 1);   
   
    }   
   
    //節點上浮,讓插入的數和父節點的數值比較,當大於父節點的時候就和節點的值相交換   
    public static void heapUp(List<Integer> heap, int index) {   
   
        //注意由於數值是從小標為一開始,當index = 1的時候,已經是根節點了   
        if (index > 1) {   
            //儲存父親的節點   
            int parent = index / 2;   
   
            //獲取相應位置的數值   
            int parentValue = (Integer) heap.get(parent);   
            int indexValue = (Integer) heap.get(index);   
            //如果父親節點比index的數值小,就交換二者的數值   
            if (parentValue < indexValue) {   
                //交換數值   
                swap(heap, parent, index);   
                //遞迴呼叫   
                heapUp(heap, parent);   
            }   
   
        }   
    }   
   
    //非遞迴實現   
    public static void heapUp2(List<Integer> heap, int index) {   
        int parent = 0;   
        for (; index > 1; index /= 2) {   
            //獲取index的父節點的下標   
            parent = index / 2;   
   
            //獲得父節點的值   
            int parentValue = (Integer) heap.get(parent);   
            //獲得index位置的值   
            int indexValue = (Integer) heap.get(index);   
               
            //如果小於就交換   
            if (parentValue < indexValue) {   
                swap(heap, parent, index);   
            }   
        }   
    }   
     /*根據樹的性質建堆,樹節點前一半一定是分支節點,即有孩子的,所以我們從這裡開始調整出初始堆*/    
     public static void adjust(List<Integer> heap){  
        for (int i = heap.size() / 2; i > 0; i--)    
            adjust(heap,i, heap.size()-1);    
            
        System.out.println("=================================================");  
        System.out.println("調整後的初始堆:");  
          print(heap);  
      }  
    /**  
     * 調整堆,使其滿足堆得定義  
     * @param i  
     * @param n  
     */    
    public static void adjust(List<Integer> heap,int i, int n) {    
         
        int child;    
        for (; i <= n / 2; ) {    
            child = i * 2;    
            if(child+1<=n&&heap.get(child)<heap.get(child+1))    
                child+=1;/*使child指向值較大的孩子*/    
            if(heap.get(i)< heap.get(child)){    
                swap(heap,i, child);    
                /*交換後,以child為根的子樹不一定滿足堆定義,所以從child處開始調整*/    
                i = child;    
                 
            }  else break;  
        }    
    }    
    
   //對一個最大堆heap排序  
    public static void heapSort(List<Integer> heap) {    
         
        for (int i = heap.size()-1; i > 0; i--) {    
        /*把根節點跟最後一個元素交換位置,調整剩下的n-1個節點,即可排好序*/    
            swap(heap,1, i);    
            adjust(heap,1, i - 1);    
        }    
    }    
   public static void main(String args[]) {   
        List<Integer> array = new ArrayList<Integer>(Arrays.asList(null,   
1, 2, 5, 10, 3, 7, 11, 15, 17, 20, 9, 15, 8, 16));  
        adjust(array);//調整使array成為最大堆  
         
        delete(array,8);//堆中刪除下標是8的元素  
        System.out.println("刪除後");  
        print(array);  
        insert(array, 99);//堆中插入  
        print(array);   
        heapSort(array);//排序  
        System.out.println("將堆排序後:");  
        print(array);  
        System.out.println("-------------------------");  
        List<Integer> array1=new ArrayList<Integer>();  
        insert(array1,0);  
        insert(array1, 1);insert(array1, 2);insert(array1, 5);  
        insert(array1, 10);insert(array1, 3);insert(array1, 7);  
        insert(array1, 11);insert(array1, 15); insert(array1, 17);  
        insert(array1, 20);insert(array1, 9);  
        insert(array1, 15);insert(array1, 8);insert(array1, 16);  
        print(array1);  
          
        System.out.println("==============================");  
        array=new ArrayList<Integer>(Arrays.asList(null,45,36,18,53,72,30,48,93,15,35));  
        adjust(array);  
          insert(array, 80);//堆中插入  
          print(array);  
         delete(array,2);//堆中刪除80的元素  
         print(array);  
         delete(array,2);//堆中刪除72的元素  
         print(array);  
                
    }   
}   

相關推薦

實現大堆插入刪除

[java] view plain copy print? import java.util.*; /** *實現的最大堆的插入和刪除操作 * @author Arthur */ public class Heap { /**

c++實現陣列的插入刪除

#include <iostream> using namespace std; void Print (int * arr,int len) { for(int i=0;i&l

實現堆的插入刪除操作

最大堆的插入 //向最大堆中插入元素, heap:存放堆元素的陣列 pub

實現大堆(包括插入從堆中取出元素)及第一種堆排序【Java版】

/** *實現最大堆 *用陣列儲存 *小優化:將swap用賦值代替,先不急著交換,先複製,再移動,最後賦值 *第一種堆排序,從小到大排序 *時間複雜度為O(nlogn) *空間複雜度O(n) */ public class MaxH

二叉搜尋樹:堆:大堆的建立,插入刪除

前面我們講到棧和佇列的時候,這兩種資料結構都是按時間的先後順序來排列,如棧是按先進後出(FILO),後入先出的原則排列。而佇列是按先進先出(FIFO)的原則排序。但有時候按這種時間原則的資料結構不能滿足使用者的一些需求,例如CPU需要執行程式的優先級別,很多時候不能靠時間順序

大堆(建立、刪除插入堆排序)

關於最大堆 什麼是最大堆和最小堆?最大(小)堆是指在樹中,存在一個結點而且該結點有兒子結點,該結點的data域值都不

Delete Node in a BST 二叉查詢樹的查詢、插入刪除 - Java實現

https://leetcode.com/problems/delete-node-in-a-bst Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return t

連結串列的插入刪除操作詳解(C語言實現+詳解註釋)

連結串列的基本操作中,連結串列結點的插入和刪除相對比較複雜,需根據結點插入位置的不同,使用合理的方法在不破壞原連結串列結構的前提下將其插入到連結串列中。 本節將詳解介紹這兩種操作的具體實現方法,讀者只需牢記實現步驟,即可輕鬆解決這兩大難點。 連結串列中插入結點 連結串列中插入結點,根據插入位置的不同,可

靜態連結串列插入刪除操作詳解(C語言程式碼實現

本節主要講解靜態連結串列的插入和刪除操作,有關靜態連結串列的詳細講解請閱讀《靜態連結串列及C語言實現》一文。 在講解靜態連結串列的插入和刪除操作之前,我們假設有如下的靜態連結串列: 圖中,array[0] 用作備用連結串列的頭結點,array[1] 用作存放資料的連結串列的頭結點,array[0]

二叉搜尋樹的查詢、值查詢、插入刪除

對於一棵二叉搜尋樹,如果不為空,它應該滿足以下三個特點:1、樹上的任一結點,該結點的值都大於它的非空左子樹的值。2、樹上的任一結點,該結點的值都小於它的非空右子樹的值。3、任一結點的左右子樹都是二叉搜尋樹。對於二叉搜尋樹的查詢,思路方法是:1、從根結點開始查詢,如果樹為空,就

C語言實現二叉樹的插入刪除

二叉樹的插入刪除://首先介紹二叉樹的插入:     //首先需要明白插入的規則:每個建好的結點p都需要從跟結點開始與根結點相比較資料域,如果根結點的資料域小於結點p,則接著將結點p與根結點的右子樹相比較,否則p將與根結點的左子樹相比較;     //繼續往下類推,一直到最後

二叉樹插入刪除操作的遞迴實現(c語言)

連結串列和陣列是最常見的資料結構,對於資料結構來說,查詢(Find),最大最小值(FindMin,FindMax),插入(Insert)和刪除(Delete)操作是最基本的操作。對於連結串列和陣列來說,這些操作的時間界為O(N),其中N為元素的個數。陣列的插入和刪除需要對其他

單鏈表插入刪除結點c語言的實現

插入節點的方法比較簡單,只需宣告一個索引的指標p和宣告一個記錄p下一個指標的next。實現過程就是,申請記憶體的指標pNew.讓p->next = pNew, pNew->next = next. 如此一來就實現了往p後面插入一個數據。 /* ========

java實現--單向連結串列的插入刪除

一、連結串列結構: (物理儲存結構上不連續,邏輯上連續;大小不固定)           概念:  鏈式儲存結構是基於指標實現的。我們把一個數據元素和一個指標稱為結點。        資料域:存數資料元素資訊的域。        指標域:儲存直接後繼位置的域。鏈式儲存結構是用

C++實現線性錶鏈式儲存結構的建立插入刪除

主函式為: #include <iostream> using namespace std; typedef int eletype; struct Node { eletyp

C++實現大堆小堆

堆 堆資料結構是一種陣列物件,它可以被視為一顆完全二叉樹結構(或者也有可能是滿二叉樹) 最大堆: 任一結點的關鍵碼均大於等於它的左右孩子的關鍵碼,其中堆頂的元素最大。(任一路徑中的元素升序排列) 最小堆: 任一結點的關鍵碼均小於等於它的左右

大堆MaxHeap小堆MinHeap的實現

       優先佇列式分支界限法解裝載問題中需要用到最大堆MazHeap,但是書上沒有給出程式碼,所以只能我們自己寫了,下面我貼出這兩個資料結構的程式碼,以供參考。解決了這兩個資料結構,那麼優先佇列式分支界限法就很好實現了。 最大堆MaxHeap: #include<

二叉樹之紅黑樹的實現-插入刪除(三)

  #include <stdio.h>   #include <stdlib.h>

DOM(創建、插入刪除元素)

http tag img 簽名 har col script value 技術分享 1.創建DOM元素 createElement(標簽名) 創建一個節點 appendChild(節點) 追加一個節點 例子:為ul插入li 並且為li元素插入一些文字

單片機調試 - 如何簡單有效的插入刪除調試語句

行號 file 有效 lin -1 源碼編譯 orm pro line #ifdef __debug #define debug(format,...) printf("File: "__FILE__", Line: %05d-------->