Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree...

28
© S. Prasitjutrakul 2013 14/10/57 1 Binary Heap สมชาย ประส ทธิ์จูตระกูล

Transcript of Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree...

Page 1: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 1

Binary Heap

สมชาย ประสทิธิจ์ตูระกลู

Page 2: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 2

priority_queue

push top,pop 5 3 99 5 4

Page 3: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 3

สร้าง Priority Queue ด้วย Binary Heap

• push : O(log n)

• pop : O(log n)

• top : (1)

• ใช้โครงสร้างแบบ balanced binary tree

ราก (root)

ปมพ่อ/แม่ (parent)

ปมลูก (child)

ต้นไม้แบบทวิภาคได้ดุลที่มี n ปม สูง log2 n

สูง 3

Page 4: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 4

ฮีปแบบทวิภาค

• Binary Heap

– มโีครงสรา้งเป็น binary tree แบบไดด้ลุ

• node เต็มทกุระดบั

• ระดบัลา่งสดุ เต็มจากซา้ยไปขวา

– ขอ้มลูของ parent node มคีา่มากกวา่ของลกู ๆ

15

50

2 10 18 20 3

21 4 2

30 5

รากเก็บค่ามากที่สุด

Page 5: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 5

การสร้างฮีปแบบทวิภาคด้วยอาเรย์

0 1 2 3 4 5 6 7 8 9 10 11 12 13

mSize mData

15

50

2 10 18 20 3

21 4 2

30 5

50 30 5 15 21 4 2 2 10 18 20 3 12

• รากเก็บที่ index 0

• ลูกซ้ายของ node ที่ index k อยู่ที่ index 2k + 1

• ลูกขวาของ node ที่ index k อยู่ที่ index 2k + 2

• พ่อของ node ที่ index k อยู่ที่ index (k – 1) / 2

0

1 2

3 4 5 6

7 8 9 10 11

Page 6: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 6

priority_queue : บริการ

priority_queue<T>

priority_queue<T, Comp>

bool empty();

size_t size();

const T& top();

void push(const T& e);

void pop();

priority_queue<T,Comp>&

operator=(priority_queue<T,Comp> rhs)

Page 7: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 7

คลาส priority_queue template <typename T, typename Comp = std::less<T>>

class priority_queue {

protected:

T* mData;

size_t mCap;

size_t mSize;

Comp mLess;

public:

priority_queue(const Comp& c = Comp()) { ... }

priority_queue(const priority_queue<T,Comp>& a) { ... }

~priority_queue() { ... }

//------------- capacity function ----------

bool empty() const { ... }

size_t size() const { ... }

//----------------- access -----------------

const T& top() const { ... }

//----------------- modifier ---------------

void push(const T& e) { ... }

void pop() { ... }

};

mCap mData

3

mSize

4 99 23 33

mLess

Page 8: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 8

constructor template <typename T, typename Comp = std::less<T> >

class priority_queue {

protected:

T* mData;

size_t mCap;

size_t mSize;

Comp mLess;

public:

priority_queue(const Comp& c = Comp()) {

mCap = 1;

mData = new T[mcap]();

mSize = 0;

mLess = c;

}

priority_queue(const priority_queue<T,Comp>& a) {

mCap = a.mCap;

mData = new T[mcap]();

for (size_t i=0; i<a.mCap; i++) mData[i] = a.mData[i];

mSize = a.mSize;

mLess = a.mLess;

}

~priority_queue() {

delete [] mData;

}

mCap mData

0

mSize

1

mLess

Page 9: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 9

constructor : initialization list template <typename T, typename Comp = std::less<T> >

class priority_queue {

protected:

T* mData;

size_t mCap;

size_t mSize;

Comp mLess;

public:

priority_queue(const Comp& c = Comp()) :

mData(new T[1]()), mCap(1),

mSize(0), mLess(c) {

}

priority_queue(const priority_queue<T,Comp>& a) :

mData(new T[a.mCap]()), mCap(a.mCap),

mSize(a.mSize), mLess(a.mLess) {

for (size_t i=0; i<a.mCap; i++) mData[i] = a.mData[i];

}

~priority_queue() {

delete [] mData;

}

...

mCap mData

0

mSize

1

mLess

Page 10: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 10

c++ : initialization list class A {

public:

A() {

a0 = 2; a1 = 3;

}

A(int x0, int x1) {

a0 = x0; a1 = x1;

}

protected:

int a0, a1;

};

class B : public A {

public:

B() { b = a0+a1; }

public:

int b;

};

int main() {

B b;

cout << b.b << endl; //5

}

class A {

public:

A() : a0(2), a1(3) {

}

A(int x0, int x1) :

a0(x0), a1(x1) {

}

protected:

int a0, a1;

};

class B : public A {

public:

B() : A(), b(a0+a1) {}

public:

int b;

};

int main() {

B b;

cout << b.b << endl; //5

}

Page 11: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 11

c++ : initialization list

class A {

public:

A() : a0(2), a1(3) { }

A(int x0, int x1) :

a0(x0), a1(x1) { }

protected:

int a0, a1;

};

class B : public A {

public:

B() : A(), b(a0+a1) {}

public:

int b;

};

int main() {

B b;

cout << b.b << endl; //5

}

class A {

public:

A() : a0(2), a1(3) { }

A(int x0, int x1) :

a0(x0), a1(x1) { }

protected:

int a0, a1;

};

class B : public A {

public:

B() : A(4,5), b(a0+a1) {}

public:

int b;

};

int main() {

B b;

cout << b.b << endl; //9

}

Page 12: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 12

c++ : initialization list class A {

public:

A() : a0(2), a1(3) { }

A(int x0, int x1) :

a0(x0), a1(x1) { }

protected:

int a0, a1;

};

class B : public A {

public:

B() {

A(4,5); // <-- สร้าง obj

b = a0 + a1; // 2+3

}

public:

int b;

};

int main() {

B b;

cout << b.b << endl; //5

}

class A {

public:

A() : a0(2), a1(3) { }

A(int x0, int x1) :

a0(x0), a1(x1) { }

protected:

int a0, a1;

};

class B : public A {

public:

B() : A(4,5), b(a0+a1) {}

public:

int b;

};

int main() {

B b;

cout << b.b << endl; //9

}

Page 13: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 13

c++ : initialization list

• เร็วกว่า (ไม่ต้องตั้งค่า data members หลายครั้ง)

• เรียก non-default ctor ของ parent class ได ้

• เรียก non-default ctor ของ member ได ้

• ใช้ตั้งค่าให้ const และ reference members

class A {

const int a;

public:

A() : a(2) { }

A(int a) : a(a) { }

};

class A {

const int a;

public:

A() { a = 2; } //ผิด

};

class A {

int & a;

public:

A(int a) : a(a) { }

...

};

int main() {

int x = 3;

A a(x);

x = 2;

...

class A {

Foo f;

public:

A() : f(0) { }

A(int a) : f(a) { }

};

Page 14: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 14

copy assignment operator : วิธีที่ 1 template <typename T, typename Comp = std::less<T> >

class priority_queue {

protected:

T* mData;

size_t mCap;

size_t mSize;

Comp mLess;

public:

...

priority_queue<T,Comp>& operator=

(const priority_queue<T,Comp>& rhs) {

using std::swap;

priority_queue<T,Comp> temp(rhs);

swap(mSize, temp.mSize);

swap(mCap, temp.mCap );

swap(mData, temp.mData);

swap(mLess, temp.mLess);

return *this;

}

...

priority_queue<int> pq1, pq2;

for (int i=0; i<10; i++) pq1.push(1);

pq2 = pq1;

pass by reference

mCap mData

3

mSize

4 99 23 33

mLess

Page 15: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 15

copy assignment operator : วิธีที่ 2 template <typename T, typename Comp = std::less<T> >

class queue {

protected:

T* mData;

size_t mCap;

size_t mSize;

Comp mLess;

public:

...

priority_queue<T,Comp>& operator=(priority_queue<T,Comp> rhs){

using std::swap;

swap(mSize, rhs.mSize);

swap(mCap, rhs.mCap );

swap(mData, rhs.mData);

swap(mLess, rhs.mLess);

return *this;

}

...

pass by value

priority_queue<int> pq1, pq2;

for (int i=0; i<10; i++) pq1.push(1);

pq2 = pq1;

// below is copy initialization

priority_queue<int> pq3 = pq1; // !!!

mCap mData

3

mSize

4 99 23 33

mLess

Page 16: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 16

empty, size, top template <typename T, typename Comp = std::less<T> >

class priority_queue {

protected:

T* mData;

size_t mCap;

size_t mSize;

Comp mLess;

public:

...

bool empty() const { // (1)

return mSize == 0;

}

size_t size() const { // (1)

return mSize;

}

const T& top() { // (1)

return mData[0];

}

...

mCap mData

3

mSize

4 99 23 33

mLess

Page 17: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 17

push( e ) : เพิ่มข้อมูล

• น า e ไปตอ่เป็นใบถัดไป (เพิม่ทา้ยในอาเรย)์

• สลับ e กบัปมพอ่ จนกวา่ e จะไมม่ากกวา่พอ่

fixUp( 5 ) 13

12 1

2 12

0 1 2 3 4 5 6

mSize mData

13 12 1 2 12 16 5

16

6

16

16

ต าแหน่งของ ตวัทีอ่าจผดิกฎ

Page 18: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 18

push( e ) template <typename T, typename Comp = std::less<T> >

class priority_queue {

protected:

...

void fixUp(size_t c) {

T tmp = mData[c];

while (c > 0) {

size_t p = c / 2;

if ( mLess(tmp, mData[p]) ) break; // tmp < mData[p]

mData[c] = mData[p];

c = p;

}

mData[c] = tmp;

}

public:

void push(const T& element) {

if (mSize+1 > mCap) expand(mCap*2);

mData[mSize] = element;

mSize++;

fixUp(mSize-1);

}

Page 19: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 19

priority_queue : less comparator template <typename T, typename Comp = std::less<T> >

class priority_queue {

protected:

...

void fixUp(size_t c) {

T tmp = mData[c];

while (c > 0) {

size_t p = (c-1) / 2;

if ( mLess(tmp, mData[p]) ) break;

mData[c] = mData[p];

c = p;

}

mData[c] = tmp;

}

public:

void push(const T& element) {

if (mSize+1 > mCap) expand(mCap*2);

mData[mSize] = element;

mSize++;

fixUp(mSize-1);

}

namespace std {

template <class T> struct less : binary_function <T,T,bool> {

bool operator() (const T& x, const T& y) const {

return x < y;

}

};

...

Page 20: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 20

priority_queue : less comparator

priority_queue<int, std::less<int>> pq1;

priority_queue<int, std::greater<int>> pq2;

priority_queue<int, CompFunc> pq3(myGreater);

priority_queue<int, CompFunc>

pq4( [](int x, int y){ return x > y; } ); // lambda

for (int i=0; i<10; i++) {

pq1.push(i);

pq2.push(i);

pq3.push(i);

pq4.push(i);

}

cout << pq1.top() << endl; // 9

cout << pq2.top() << endl; // 0

cout << pq3.top() << endl; // 0

cout << pq4.top() << endl; // 0

typedef bool(*CompFunc)(int, int);

bool myGreater(int a,int b) {

return a > b;

}

Page 21: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 21

push( e ) : อาเรย์เต็มก็ขยาย template <typename T, typename Comp = std::less<T> >

class priority_queue {

protected:

...

void expand(size_t capacity) {

T *arr = new T[capacity]();

for (size_t i = 0;i < mSize;i++) arr[i] = mData[i];

delete [] mData;

mData = arr; mCap = capacity;

}

...

public:

void push(const T& element) {

if (mSize+1 > mCap) expand(mCap*2);

mData[mSize] = element;

mSize++;

fixUp(mSize-1);

}

Page 22: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 22

pop( ) : ลบตัวมากสุด

• เก็บรากไวเ้ป็นค าตอบ

• ยา้ยขอ้มลูทีใ่บลา่งขวาสดุ มาเก็บทีร่าก

• สลับขอ้มลูทีร่ากลงมา จนกวา่พอ่จะไมน่อ้ยกวา่ลกู

fixDown( 0 )

13

1 2 11

0 1 2 3 4 5 6

mSize mData

15 13 9 2 11 1 6 1 5

ต าแหน่งของ ตวัทีอ่าจผดิกฎ

9

15 1

1

1

Page 23: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 23

pop( e ) : ลบตัวมากสุด template <typename T, typename Comp = std::less<T> >

class priority_queue {

protected:

...

void fixDown(size_t p) {

T tmp = mData[p];

size_t c;

while ((c = 2*p + 1) < mSize) {

if (c+1 < mSize && mLess(mData[c],mData[c+1])) c++;

if ( mLess(mData[c],tmp) ) break;

mData[p] = mData[c];

p = c;

}

mData[p] = tmp;

}

public:

void pop() {

mData[0] = mData[mSize-1];

mSize--;

fixDown(0);

}

Page 24: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 24

เวลาการท างาน

• top : O(1)

• push : fixUp = O(h) = O(log n)

• pop : fixDown = O(h) = O(log n)

มีข้อมูล n ตัว สูง log2 n

Page 25: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 25

priority_queue(T a[], int n, const Comp& c = Comp() ) :

mData(new T[n]()), mCap(n), mSize(0), mLess(c) {

for (int i=0; i<n; i++) push(a[i]);

}

4

1 3

6

การสร้างฮีปแบบทวิภาคด้วยการค่อย ๆ เพิ่ม

1 1

3

3

1 4

3

1

4

1 3

6

4 3

1

6

4 3

1 8

8

6 3

1 4

8

6 3

1 4 10

10

6 8

1 4 3 11

10

6 8

1 4 3

11

6 10

1 4 3 8

log2 1 + log2 2 + log2 3 +...+ log2 n < log2 n! = O(n log n)

log2 1 log2 2 log2 3

log2 4 log2 5

log2 6 log2 7

Page 26: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 26

การสร้างฮีปแบบทวิภาคด้วยการค่อย ๆ ปรับ

1 25 12 10 11 27 9 1 20 25 21 7 19

0 1 2 3 4 5 6 7 8 9 10 11

25

12 10

11 27 9 1

20 25 21 7 19

19

9

25

11

19

10

27

21

12

27

25

priority_queue(T a[], int n, const Comp& c = Comp() ) :

mData(new T[n]()), mCap(n), mSize(n), mLess(c) {

for (int i=0; i<n; i++) mData[i] = a[i];

for (int i=mSize/2-1; i>=0; i--) fixDown(i);

}

Page 27: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 27

การสร้างฮีปแบบทวิภาคด้วยการค่อย ๆ ปรับ

0

2

h

h k

k

k

สูง จ านวนต้น

4 1

3 2

2 4

1 8

0 16

k 2h – k

h

fixdown ในต้นไม้สูง k เกิดการสลับข้อมูลไม่เกิน k ครั้ง

0

2

h

h k

k

k

0

2 2

h

h k

k

k

0

2 2h k

k

k

= 2h+1 = O(n)

2

Page 28: Binary Heap - Nattee · • Binary Heap – มีโครงสร างเป็น binary tree แบบได ดุล • node เต็มทุกระดับ • ระดับล

© S. Prasitjutrakul 2013 14/10/57 28

ฮีปมากสุด / ฮีปน้อยสุด (Max/Min Heap)

• ฮีปมากสุด

– ข้อมูลของ parent node มีค่ามากกว่าของลูก ๆ

• ฮีปน้อยสุด

– ข้อมูลของ parent node มีค่าน้อยกว่าของลูก ๆ

50

1 25

21 3

1

50 3

25 21

max heap min heap