一般的に使用されるデータ構造のヒープ(ヒープ)

1はじめに

アレイとリンクリスト           に関する前回の記事に続いて、 今日それについて話しましょう。オペレーティングシステムにはスタックの概念があることは誰もが知っています。Javaを学んだ学生は、Java仮想マシンにもスタックがあることを知っています。スタックは、関数のコンテキストと、システムによって管理されるいくつかの基本的なタイプの変数を管理する役割を果たします。ヒープは新しく作成されたオブジェクトを格納し、そのアドレスをスタック内の参照変数にポイントします。参照がない場合、オブジェクトはガベージオブジェクトになり、最終的にガベージコレクターによって収集されます。しかし、ここで話したいのは、メモリのヒープではありません。メモリは通常、リンクされたリストの形式で管理されます。ただし、データ構造のヒープの概念は、優先キューと同等です。

2.ヒープの定義と性質

   1.定義

           ヒープは完全なバイナリツリーです。いわゆる完全なバイナリツリーとは、ツリーの各ノードの位置と完全なバイナリツリー内の位置を指します。いわゆる完全なバイナリツリーとは、ツリーの各レイヤー(つまり、ツリー)内のノードの最大値を指します。のすべてのレイヤーが塗りつぶされます);

           最大ヒープヒープ内の親ノードの値は常に子ノード(優先キュー)よりも大きくなります

           最小ヒープ:親ノードの値は常に子ノードよりも小さい

                                  

     2.自然とノードの位置の関係

              1.親ノードの位置はi、左側の子ノードの位置は2i + 1、右側の子ノードの位置は2i +2であることがわかっています。

              2.子ノードの位置はiであり、その親ノードの位置は(i-1)/ 2であることがわかっています。

     3.ネイチャーツーハイト

              ヒープの高さは、ルートノードから最も遠いリーフノードまでのステップ数であり、ヒープのレイヤー数から1を引いた数に等しくなります。合計n個のノードがあるとすると、これらのn個のノードで構成されるヒープの高さはですフロア(logn)。ここで、対数は2を底とします。

              ヒープの最下層が満たされている場合、最小層のノード数は2 ^ {h}、前のすべての層のノード2 ^ {h} -1合計は、このヒープ内のノード総数はのようになります。2 ^ {h + 1} -1

     4.ヒープ構築のプロセス

             図に示すように、最小ヒープを構築します。実装プロセスでは、各要素をヒープの最後のビットに挿入してから、ヒープ操作を上向きに実行し続けます。次のコード実装は、これをより明確に示します。

                  

3.基本的な機能コードの実現

           基本的な機能は3つのポイントが含まれています。

           1.ヒープに新しい要素を追加し、最初に要素を最後の位置に挿入してから、位置が変更されなくなるまで親ノードとの比較を続けます

           2.ヒープの最上位要素をポップし、ポップ後に最後のビットを最初の位置に配置し、位置が変更されなくなるまで子ノードと比較し続けます。

           3.優先キュー:配列をヒープに変えることは、実際には、各要素を空のヒープに挿入し、優先度でソートすることを意味します。

#-*- coding:utf-8 -*-
#实现一个最大堆
#1.使用数组来存放元素
#2.两个核心 方法 shift_up(将元素和父节点比较,如果顺序不对就更换位置) 
#shift_down (将元素和子节点比较,如果顺序不对就更换位置)
#3.添加元素 加入到最后面  然后进行 shift_up(-1)进行堆顺序调整
#4.取出元素 弹出第一个  将最后一个放在第一的位置  然后shift_down(0)进行堆顺序调整
class MaxHeap(object):
    #双下划线表示私有 外部不可以访问 子类也不可以
    # 单下划线表示半私有 外部可以访问 子类可以访问
    def __init__(self):
        self.array=[] #用数组来存放元素
    def _parent(self,index):
        return int((index-1)/2)
    def _leftchild(self,index):
        return int(index*2+1)
    def _rightchild(self,index):
        return int(index*2+2)
    def get_size(self):
        return len(self.array)
    # 将每一个元素和父节点进行比较,如果大于父节点的值则进行位置交换
    def shift_up(self,K):
        parent = self._parent(K)
        if K>0 and self.array[K]>self.array[parent]:
            self.array[K],self.array[parent]=self.array[parent],self.array[K]
            self.shift_up(parent)
    #将节点和自己的子节点比较,如果子节点大于父节点则调换位置
    def shift_down(self,K):
        left_child = self._leftchild(K)
        right_child = self._rightchild(K)
        array_size = self.get_size()
        max_position = K
        if left_child+1<array_size and self.array[max_position] < self.array[left_child]:
            max_position = left_child
        if right_child+1 < array_size and self.array[max_position] < self.array[right_child]:
            max_position = right_child
        if max_position != K:
            self.array[max_position], self.array[K] = self.array[K], self.array[max_position]
            self.shift_down(max_position)
    #将一个元素插入堆,添加到最后一位,然后执行shift_up
    def push(self,V):
        self.array.append(V)
        self.shift_up(len(self.array)-1)
    #删除元素,顶部弹出,将最后一个元素放入顶部,执行shift_down
    def pop(self):
        max_value = self.array[0]
        self.array[0],self.array[len(self.array)-1] = self.array[len(self.array)-1],self.array[0]
        self.array.pop(-1)
        self.shift_down(0)
        return max_value
    #查看堆顶元素
    def find_max(self):
        return self.array[0]
    #将一个数组进行堆化,就是将元素一个个插入堆中
    def heapify(self,arr):
        for i in arr:
            self.push(i)
        return self.array
    #遍历堆
    def listHeap(self):
        return self.array
array = [1,2,3,4,17,6,7,8,9,10]
maxHeap = MaxHeap()
print(maxHeap.heapify(array))
print(maxHeap.pop())
maxHeap.push(15)
print(maxHeap.listHeap())

 4.ヒープアプリケーション

  1.ヒープソート

         ヒープソートのアイデアは、データのセットをヒープアップしてから、ヒープの最上位要素を1つずつポップすることです。全体的な複雑さはO(nlogn)です!

    def heap_sort(self,data):
        self.heapify(data)
        heap_sort = []
        for i in self.array:
            heap_sort.append(i)
        return heap_sort

    2.上位K個の最大数を取得します

        実際、上記のヒープソートの考え方と一致していますが、すべての要素をソートする必要はありません。要素が積み上げられた直後に、パイルの上部にK回飛び出します。

    def get_max_k(self,data,K):
        self.heapify(data)
        max_k = []
        for i in range(K):
            max_k.append(self.pop())
        return max_k

5.まとめ

       この記事では、データ構造のヒープの概念を紹介します。これは、オペレーティングシステムのメモリ管理のヒープの概念ではありません。ヒープは完全なバイナリツリーであることがわかっています。最大のヒープの場合、各ノードの値はその子ノードの値よりも大きくなり(最小のヒープの反対)、ヒープの上部にある要素が最大になります。ヒープの場合、通常、保存とフェッチの2つの操作があります。保存するときは、新しい値を最後のビットに挿入してから、スタックを続けます。フェッチすると、ヒープの上部にある要素がポップされ、最後の要素がヒープの上部に配置され、ヒープ操作が下方向に続行されます。  

         ヒープ内のデータは順序付けられておらず、親ノードが子ノードよりも大きいことのみに準拠しており、ヒープの最上位要素のみを使用できることに気付きました。比較的大まかなシーケンスと言えます。しかし、その要件は多くないため、要素の挿入と削除を非常に簡単に行うことができます。また、ヒープの最上位要素は常に最大であるため、ヒープソート、優先キュー、上位K個の最大数などの複雑な機能を簡単に実装できます。その限界も利点と言えます。

6.ゴシップ

          人々は「あなたはいい人だ、彼はいい豚だ」と言う。人々の目には、おいしい肉と大きな体を持った豚はいい豚だ。豚の目には、満腹で仕事に行かなければならない人々は、単に大きな愚か者の束であり、骨髄の深さから奴隷にされた生き物のグループです。人間の言葉は少し複雑すぎるので、退屈な英語の言葉と一緒に暮らしたくありません。基本的に、言語の複雑さは嘘の数に正比例します。好きなことを表現するだけの場合は、言語、抱擁、キスさえ必要ありません。相手を見るだけで十分に理解できます。しかし、それが気に入らないが表現したい場合は、言語しか使用できません。豚の場合、それははるかに簡単です。彼らの世界には、ハム、ハム、ハムしかありません!これは最も先進的な言語であり、最も効果的な表現方法です。好きはハム、嫌いはハム、おいしいはハム、美味しくないはハムです。自然言語を深く学ぶという観点からは、人間の言語は最も原始的なワンホットコードであり、シンプルでシンプルです。豚の言語、どのように高レベルの抽象化、どのように完璧なカプセル化、絶対的に高い凝集性、そして完全に緩く結合されているかを見てください!善良な人々と豚との関係と言語について話しましょう。人々の言語は一種の装飾と変装であり、真実は絶対に真実であるため、人々が真実を知るのを防ぐための最良の方法です。多くの場合、私たちが考えることは私たちが言うことであると感じますが、実際には、私たちは思考に近い言語での表現を見つけるだけです。言語シンボルが私たちの主な考え方になっています。言語と論理が私たちの考え方であることを注意深く思い出してください。梅林に入るとき、リンゴを選ぶことは決してありません。同じ言語で真実はありません。豚をもう一度見てください。強姦犯で有罪判決を受けた豚はなく、仲間に引き抜かれ撃たれた豚もいません。つまり、彼らの社会的定義には、悪いという概念はありません。これはまた、誰もが八尾と俊であるという有名な言葉を証明します。ですから、良い人はまったくいないのですが、逆に悪い豚はまったくいません!

      すみません、素晴らしい人間の言語です!私がとてもネガティブな理由は、私が英語の言葉に夢中になっているからです。

        

超ハンサムな女性

 

 

 

おすすめ

転載: blog.csdn.net/gaobing1993/article/details/108768791