heap sort

20
Nguyenjjdsds êfefefe Heap Sort Friday, 11. January 2008, 12:46 LẬP TRÌNH Heap là một cấu trúc dữ liệu , có thể được biểu diễn thông qua 2 cách : -Dạng thứ 1: Dạng cây nhị phân có đặc điểm là node cha thì lớn hơn 2 node con trực tiếp của nó . -Dạng thứ 2: nếu ta đánh số các node theo thứ tự từ trên xuống và từ trái qua . Bắt đầu là node root = 0 , thì ta có thể định nghĩa heap thông qua mảng một chiều , có đặc điểm là phần tử thứ k sẽ lớn hơn các phần tử thứ 2k+1 và 2k+2 . Ta có thể dễ nhận thấy là phàn tử thứ 0 sẽ tương ứng với root trong cây ở cách biểu diễn thứ 1 Nguyên tắc sắp xếp của heap sort Dựa vào tính chất của heap trong cách biểu diễn thứ 1 và thứ 2 , ta có thể thấy phần tử đầu tiên trong cách biểu diễn theo mảng sẽ là phần tử lớn nhất ---> cách sắp xếp đơn giản là : ( Gọi mảng ban đầu là A ) Khởi tạo : Tạo heap từ mảng ban đầu đã cho (mảng A ) 1. Lấy phần tử đầu tiên trong mảng ra bỏ vào mảng kết quả 2. Tạo lại heap từ mảng A 3.Quay lại bước 1 VD : Ta lấy một mảng đã được tạo thành một heap : y r p d f b k a c Lấy phần tử đầu tiên là y bỏ vào mảng kết quả C = { y } khi này A = r p d f b k a c Tạo heap A = r f p d c b k a 1

Upload: mrduc

Post on 22-Nov-2014

403 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Heap Sort

Nguyenjjdsds êfefefe

Heap SortFriday, 11. January 2008, 12:46

LẬP TRÌNH

Heap là một cấu trúc dữ liệu , có thể được biểu diễn thông qua 2 cách :

-Dạng thứ 1: Dạng cây nhị phân có đặc điểm là node cha thì lớn hơn 2 node con trực tiếp

của nó .

-Dạng thứ 2: nếu ta đánh số các node theo thứ tự từ trên xuống và từ trái qua . Bắt đầu là

node root = 0 , thì ta có thể định nghĩa heap thông qua mảng một chiều , có đặc điểm là

phần tử thứ k sẽ lớn hơn các phần tử thứ 2k+1 và 2k+2 . Ta có thể dễ nhận thấy là phàn

tử thứ 0 sẽ tương ứng với root trong cây ở cách biểu diễn thứ 1

Nguyên tắc sắp xếp của heap sort

Dựa vào tính chất của heap trong cách biểu diễn thứ 1 và thứ 2 , ta có thể thấy phần tử

đầu tiên trong cách biểu diễn theo mảng sẽ là phần tử lớn nhất ---> cách sắp xếp đơn giản

là : ( Gọi mảng ban đầu là A )

Khởi tạo : Tạo heap từ mảng ban đầu đã cho (mảng A )

1. Lấy phần tử đầu tiên trong mảng ra bỏ vào mảng kết quả

2. Tạo lại heap từ mảng A

3.Quay lại bước 1

VD : Ta lấy một mảng đã được tạo thành một heap :

y r p d f b k a c

Lấy phần tử đầu tiên là y bỏ vào mảng kết quả C = { y }

khi này A = r p d f b k a c

Tạo heap A = r f p d c b k a

Lấy phần tử đầu tiên ra là r bỏ vào mảng C = { r y }

Khi này A = { f p d c b k a }

Tạo heap cho A = { p f k d c b a}

1

Page 2: Heap Sort

Nguyenjjdsds êfefefe

Lấy phần tử đầu tiên ra là p bỏ vào mảng C = { p r y }

Khi này A = { f k d c b a }

Tạo heap cho A = { k f b d c a}

Lấy phần tử đầu tiên ra là k bỏ vào mảng C = { k p r y }

Khi này A = { f b d c a }

Tạo heap cho A = { f d b a c}

Lấy phần tử đầu tiên ra là f bỏ vào mảng C = { f k p r y }

Khi này A = { b d c a }

Tạo heap cho A = { d c b a}

Lấy phần tử đầu tiên ra là d bỏ vào mảng C = {d f k p r y }

Khi này A = { c b a }

Tạo heap cho A = { c a b }

Lấy phần tử đầu tiên ra là c bỏ vào mảng C = {c d f k p r y }

Khi này A = { b a }

Tạo heap cho A = { b a }

Lấy phần tử đầu tiên ra là b bỏ vào mảng C = {b c d f k p r y }

Khi này A = { a }

Tạo heap cho A = { a }

Kết thúc ta có được mảng C đã có thứ tự .

Cải tiến:

Ta có thể hạn chế việc sử dụng thêm mảng C bằng cách tận dụng luôn mảng A ban đầu .

Ta làm như sau

A = y r p d f b k a c

Bước 1 :

Lấy y ra

2

Page 3: Heap Sort

Nguyenjjdsds êfefefe

Lấy c ra

Bỏ y vào chổ của c .

Bỏ c vào chỗ của y

Khi ta bỏ y vào chỗ của c thì giống như ta bỏ y vảo mảng C .

Khi này mảng A sẽ coi như gồm 2 phần A = c r p d f b k a ---- y

Bước 2 : tạo heap cho phần đứng trước của A là c r p d f b k a

Phần sau là chứa y để nguyên

Ta sẽ có A mới là : r f p d c b k a -- y

Quay lại bước 1 : Lấy r , a ra và swap r và a

A sẽ thành A= a f p d c b k -- r y

Tạo heap cho A = p f k d c b a -- r y

...........

Làm tương tự đến khi kết thúc

Qua VD ta thấy rằng phần quan trọng nhất là làm sao sinh ra heap từ một mảng cho trước

Sau đây là phần code cho phần cải tiến

Giải thuật

Post Condition : Dùng để phục hồi lại heap .

Pre Condition :

Ta sẽ có A mới là : r f p d c b k a -- y

Quay lại bước 1 : Lấy r , a ra và swap r và a

A sẽ thành A= a f p d c b k -- r y

Tạo heap cho A = p f k d c b a -- r y

Thì khi này current chính là a

low là 0

3

Page 4: Heap Sort

Nguyenjjdsds êfefefe

high là 7

Code:

void Sortable_List<Record>::insert_heap(const Record &current, int low , int high

{

int large ; 

large = 2*low+1 ;

while ( large <= high ) {

if (large < high && entry[large] < entry[large+1] )

large ++ ;

if(current >= entry[large] ) 

{

break ;

}

else 

{

entry[low] = entry[large] ; 

low = large ;

large = 2 * low + 1 ;

}

}

entry[low] = current ; 

}

Tạo ra heap lúc ban đầu , lúc chưa chạy giải thuật

void Sortable_List<Record>::bulidheap()

{

int low ;

for ( low = count / 2- 1; low >= 0 ; low -- )

{

Record current = entry[low] ;

4

Page 5: Heap Sort

Nguyenjjdsds êfefefe

insert_heap(current, low, count -1) ;

}

}

void Sortable_List<Record>::heapsort ()

{

Record current ;

int last_unsorted ;

buildheap() ;

for ( last_unsorted = count -1 ; last_unsorted > 0 ; last_unsorted -- )

{

current = entry[ last_unsorted] ;

entry[last_unsorted] = entry[0] ;

insert_heap(current,0,last_unsorted-1) ;

}

}

5

Page 6: Heap Sort

Nguyenjjdsds êfefefe

Thuật toán Sắp xếp vun đống - Heap Sort

Sắp xếp vun đống (Heapsort) dựa trên một cấu trúc dữ liệu được gọi là đống nhị phân (binary heap), gọi đơn giản là đống. Trong mục này chỉ nói về đống trong bài toán sắp xếp.

Đống (Heap)

 Ví dụ về mảng và cây nhị phân tương ứng

Mỗi mảng a[1..n] có thể xem như một cây nhị phân gần đầy (có trọng số là các giá trị của mảng), với gốc ở phần tử thứ nhất, con bên trái của đỉnh a[i] là a[2*i] con bên phải là a[2*i+1] (nếu mảng bắt đầu từ 1 còn nếu mảng bắt đầu từ 0 thì 2 con là a[2*i+1]

và a[2*i+2] ) (nếu 2*i<=n hoặc 2*i+1<=n, khi đó các phần tử có chỉ số lớn hơn   không có con, do đó là lá).

Ví dụ mảng (45,23,35,13,15,12,15,7,9) là một đống

Một cây nhị phân, được gọi là đống cực đại nếu khóa của mọi nút không nhỏ hơn khóa các con của nó. Khi biểu diễn một mảng a[] bởi một cây nhi phân theo thứ tự tự nhiên điều đó nghĩa là a[i]>=a[2*i] và a[i]>=a[2*i+1] với mọi i =1..int(n/2). Ta cũng sẽ gọi mảng

6

Page 7: Heap Sort

Nguyenjjdsds êfefefe

như vậy là đống. Như vậy trong đống a[1] (ứng với gốc của cây) là phần tử lớn nhất. Mảng bất kỳ chỉ có một phần tử luôn luôn là một đống.

Một đống cực tiểu được định nghĩa theo các bất đẳng thức ngược lại: a[i]<=a[2*i] và a[i]<=a[2*i+1]. Phần tử đứng ở gốc cây cực tiểu là phần tử nhỏ nhất.

Vun đống

Việc sắp xếp lại các phần tử của một mảng ban đầu sao cho nó trở thành đống được gọi là vun đống.

Vun đống tại đỉnh thứ i

 

Nếu hai cây con gốc 2 * i và 2 * i + 1 đã là đống thì để cây con gốc i trở thành đống chỉ việc so sánh giá trị a[i]với giá trị lớn hơn trong hai giá trị a[2 * i] và a[2 * i + 1], nếu a[i] nhỏ hơn thì đổi chỗ chúng cho nhau. Nếu đổi chỗ cho a[2 * i], tiếp tục so sánh với con lớn hơn trong hai con của nó cho đên khi hoặc gặp đỉnh lá. (Thủ tục DownHeap trong giả mã dưới đây)

Vun một mảng thành đống

Để vun mảng a[1..n] thành đống ta vun từ dưới lên, bắt đầu từ phần tử a[j]với j =Int(n/2) ngược lên tới a[1]. (Thủ tục MakeHeap trong giả mã dưới đây) kho qua

Sắp xếp bằng vun đốngĐổi chỗ (Swap): Sau khi mảng a[1..n] đã là đống, lấy phần tử a[1] trên đỉnh của đống ra khỏi đống đặt vào vị trí cuối cùng n, và chuyển phần tử thứ cuối cùng a[n] lên đỉnh đống thì phần tử a[n] đã được đứng đúng vị trí.Vun lại: Phần còn lại của mảng a[1..n-1] chỉ khác cấu trúc đống ở phần tử a[1]. Vun lại mảng này thành đống với n-1 phần tử.Lặp: Tiếp tục với mảng a[1..n-1]. Quá trình dừng lại khi đống chỉ còn lại một phần tử.

7

Page 8: Heap Sort

Nguyenjjdsds êfefefe

Ví dụ

Cho mảng a=(2,3,5,6,4,1,7)

Ở đây n = 7. Các phần tử từ a[4] đến a[7] là lá.

Vun đống Vun cây gốc a[3] ta được mảng a=(2,3,7,6,4,1,5) Vun cây gốc a[2] ta được mảng a=(2,6,7,3,4,1,5) Vun cây gốc a[1] ta được mảng a=(7,6,5,3,4,1,2)

Bây giờ a=(7,6,5,3,4,1,2) đã là đống.

Sắp xếp Đổi chỗ a[1] với a[7]: a=(2,6,5,3,4,1,7)

và vun lại mảng a[1..6] ta được mảng a=(6,4,5,3,2,1,7) Đổi chỗ a[1] với a[6]: a=(1,4,5,3,2,6,7)

và vun lại mảng a[1..5] ta được mảng a=(5,4,2,3,1,6,7) Đổi chỗ a[1] với a[5]: a=(1,4,2,3,5,6,7)

và vun lại mảng a[1..4] ta được mảng a=(4,3,2,1,5,6,7) Đổi chỗ a[1] với a[4]: a=(1,3,2,4,5,6,7)

và vun lại mảng a[1..3] ta được mảng a=(3,1,2,4,5,6,7) Đổi chỗ a[1] với a[3]: a=(2,1,3,4,5,6,7)

và vun lại mảng a[1..2] ta được mảng a=(2,1,3,4,5,6,7) Đổi chỗ a[1] với a[2]:a=(1,2,3,4,5,6,7) Mảng còn lại chỉ một phần tử. Quá trình sắp xếp đã xong.

==Mã giả==(DowHeap)

function heapSort(a[1..count], count) { var int end := count MakeHeap(a,count) while end > 0 swap(a[end], a[1]) end := end - 1 DownHeap(a, 1, end) }function MakeHeap(a, count) { var int start := Int(count/2) while start > 0 DownHeap(a, start, count)

8

Page 9: Heap Sort

Nguyenjjdsds êfefefe

start := start - 1 } function DownHeap(a, start, count) { var int i := start, j

while i * 2 <= count { j := i * 2 if j+1 <= count and a[j] < a[j + 1] j := j + 1 if a[i] < a[j] swap(a[i], a[j]) i := j else return } }

Lưu ý là dãy số bắt đầu từ 1 -> n chứ ko phải 0 -> n-1 nha.

Code (Yêu cầu xem để hiểu & gõ lại, nên hạn chế Copy & Paste):#include<iostream.h>#include<conio.h>

void nhap(int a[50],int &n){   cout<<"Nhap n=";cin>>n;   for(int i=1;i<=n;i++)   {      cout<<"a["<<i<<"]=";cin>>a[i];   }}void xuat(int a[50],int n){   for(int i=1;i<=n;i++)   {      cout<<"\t"<<a[i];   }}void HoanVi(int &a,int &b){   int temp=a;a=b;b=temp;}void Shift(int a[50],int L,int R){   int CsCha=L,CsCon=2*CsCha,LaHeap=0;   int Cha=a[CsCha];   while((!LaHeap) && (CsCon<=R))   {      if(CsCon<R)         if(a[CsCon]<a[CsCon+1]) CsCon++;      if(Cha>a[CsCon]) LaHeap=1;      else      {         a[CsCha]=a[CsCon];

9

Page 10: Heap Sort

Nguyenjjdsds êfefefe

         CsCha=CsCon;         CsCon=2*CsCha;      }      a[CsCha]=Cha;   }}void TaoHeapDayDu(int a[50],int n){   int L=n/2,R=n;   while(L>=1)   {      Shift(a,L,R);      L--;   }}void HeapSort(int a[50],int n){   TaoHeapDayDu(a,n);   int L=1,R=n;   while(R>1)   {      HoanVi(a[1],a[R]);      Shift(a,L,--R);   }}void main(){   int a[50], n;

   nhap(a,n);   cout<<"Mang da nhap: ";   xuat(a,n);   HeapSort(a,n);   cout<<"\n\nMang da sap xep: ";   xuat(a,n);   cout<<endl;   getch();}

Code (Yêu cầu xem để hiểu & gõ lại, nên hạn chế Copy & Paste):#include<iostream.h>#include<conio.h>

void nhap(int a[50],int &n){   cout<<"Nhap n=";cin>>n;   for(int i=1;i<=n;i++)   {      cout<<"a["<<i<<"]=";cin>>a[i];   }}void xuat(int a[50],int n){   for(int i=1;i<=n;i++)   {      cout<<"\t"<<a[i];   }}void HoanVi(int &a,int &b){   int temp=a;a=b;b=temp;}

10

Page 11: Heap Sort

Nguyenjjdsds êfefefe

void Shift(int a[50],int L,int R){   int CsCha=L,CsCon=2*CsCha,LaHeap=0;   int Cha=a[CsCha];   while((!LaHeap) && (CsCon<=R))   {      if(CsCon<R)         if(a[CsCon]<a[CsCon+1]) CsCon++;      if(Cha>a[CsCon]) LaHeap=1;      else      {         a[CsCha]=a[CsCon];         CsCha=CsCon;         CsCon=2*CsCha;      }      a[CsCha]=Cha;   }}void TaoHeapDayDu(int a[50],int n){   int L=n/2,R=n;   while(L>=1)   {      Shift(a,L,R);      L--;   }}void HeapSort(int a[50],int n){   TaoHeapDayDu(a,n);   int L=1,R=n;   while(R>1)   {      HoanVi(a[1],a[R]);      Shift(a,L,--R);   }}void main(){   int a[50], n;

   nhap(a,n);   cout<<"Mang da nhap: ";   xuat(a,n);   HeapSort(a,n);   cout<<"\n\nMang da sap xep: ";   xuat(a,n);   cout<<endl;   getch();}

11

Page 12: Heap Sort

Nguyenjjdsds êfefefe

Cái dòng này sẽ làm cho giải thuật sai nếu duyệt mảng từ 0:int CsCha=L, CsCon=2*CsCha ,LaHeap=0;nếu nút gốc là 0 thì thằng CsCon=2*0=0 => sai! B-)hiểu lý do vì sao phải chạy từ 1 rồi nhé ^^Code (Yêu cầu xem để hiểu & gõ lại, nên hạn chế Copy & Paste):void Shift(int a[50],int L,int R){   int CsCha=L,CsCon=2*CsCha+1,LaHeap=0; //chay tu 1: int ...,CsCon=2*CsCha,...;   int Cha=a[CsCha];   while((!LaHeap) && (CsCon<=R))   {      if(CsCon<R)         if(a[CsCon]<a[CsCon+1]) CsCon++;      if(Cha>a[CsCon]) LaHeap=1;      else      {         a[CsCha]=a[CsCon];         CsCha=CsCon;         CsCon=2*CsCha;      }      a[CsCha]=Cha;   }}void TaoHeapDayDu(int a[50],int n){   int L=n/2-1,R=n-1; //chay tu 1: int L=n/2, R=n;   while(L>=0)           //chay tu 1: while(L>=1)   {      Shift(a,L,R);      L--;   }}void HeapSort(int a[50],int n){   TaoHeapDayDu(a,n);   int L=0,R=n-1;    //chay tu 1: int L=1,R=n;   while(R>0)         //chay tu 1: while(R>1)   {      HoanVi(a[0],a[R]);     //chay tu 1: HoanVi(a[1],a[R]);      Shift(a,L,--R);   }}

Biến LaHeap thực chất dùng để nhận biết khi nào Cha>a[CsCon] thì thoát hàm while, vì vậy có thể ko dùng biến này bằng cách:tại if(Cha>a[CsCon]) LaHeap=1; => if(Cha>a[CsCon]) break;hàm while bỏ phần điều kiện xét LaHeap đi => while(CsCon<=R)(vì sao anh giải thích chổ này? vì lúc chiều thực hành Cô hỏi biến LaHeap dùng làm gì

hok ai biết  ) )

Còn cái đoạn này là "nguyên thủy" anh hay gặp ở các giáo trình cũ của các trường khác, duyệt mảng từ 0, dễ hiểu ko rườm rà như cái trên

Code (Yêu cầu xem để hiểu & gõ lại, nên hạn chế Copy & Paste):void nhap(int a[50],int &n){   cout<<"Nhap n=";cin>>n;   for(int i=0;i<n;i++)   {      cout<<"a["<<i<<"]=";cin>>a[i];   }

12

Page 13: Heap Sort

Nguyenjjdsds êfefefe

}void xuat(int a[50],int n){   for(int i=0;i<n;i++)   {      cout<<"\t"<<a[i];   }}void HoanVi(int &a,int &b){   int temp=a;a=b;b=temp;}//ham dieu chinh phan tu a[i]void Heapify(int a[50],int n,int i){   int saved=a[i]; //luu lai gia tri cua nut i   while(i<n/2)     //a[i] ko phai la nut la'   {      int child=2*i+1;    //nut con ben trai cua a[i]      if(child<n-1)         if(a[child]<a[child+1]) child++;      if(saved>=a[child]) break;      a[i]=a[child];      i=child;   }   a[i]=saved;       //gan gia tri cua nut i da luu vao vi tri moi}//xay dung ma a binh thuong tro thanh 1 Heapvoid BuildHeap(int a[50],int n){   for(int i=n/2-1;i>=0;i--)      Heapify(a,n,i);}void HeapSort(int a[50],int n){   BuildHeap(a,n);   for(int i=n-1;i>=0;i--)   {      HoanVi(a[0],a[i]);      Heapify(a,i,0);   }}void main(){   int a[50], n;

   nhap(a,n);   cout<<"Mang da nhap: ";   xuat(a,n);   HeapSort(a,n);   cout<<"\n\nMang da sap xep: ";   xuat(a,n);   cout<<endl;   getch();}

VII - Giải thuật Heap SortHeap là một cây nhị phân được biểu diễn bằng một mảng mà mảng đó biểu diễn một cây nhị phân hoàn chỉnh sao cho khoá ở node cha bao giờ cũng lớn hơn khoá của node con của nó.

13

Page 14: Heap Sort

Nguyenjjdsds êfefefe

Sắp xếp kiểu Heap Sort được tiến hành qua hai giai đoạn. Giai đoạn đầu tiên cây nhị phân biểu diễn bảng khoá được biến đổi đưa về một heap. Như vậy, đối với heap nếu j là chỉ số của node con thì [j/2] là chỉ số của node cha. Như vậy node gốc của heap là khoá có giá trị lớn nhất trong mọi node.Để chuyển từ cây nhị phân bình thường thành một cây nhị phân heap. Chúng ta thực hiênh duyệt từ dưới lên (bottom up). Node lá đương nhiên là một heap. Nếu cây con bên trái và cây con bên phải đều là một heap thì toàn bộ cây cũng là một heap. Như vậy để tạo thành một heap chúng ta thực hiện so sánh nội dung node bên trái , nội dung node bên phải với node cha của nó, node nào có giá trị lớn hơn sẽ được thay đổi làm node cha. Quá trình lần lượt ngược lại cho tới khi gặp node gốc thì nội dung node gốc chính là khoá có giá trị lớn nhất.Giai đoạn hai của thuật giải là đưa nội dung của node gốc về vị trí cuối cùng và nội dung của node cuối cùng được thay vào cị trí node gốc sau đó coi như node cuối cùng đã bị loại bỏ vì thực tế node cuối cùng là giá trị lớn nhất trong dãy số.Cây mới được hình thành (không kể phần tử loại bỏ) không phải là một heap, chúng ta lại thực hiện vun thành đống và thực hiện tương tự như trên cho tới khi đống còn một phần tử là phần tử bé nhất của dãy.Độ phức tạp của Heap Sort là : Cmã = Cmin = O(n logn) cơ số hai.Giải thuật được cài đặt như sau:Code:

#include <conio.h>#include <stdlib.h>#include <alloc.h>#include <dos.h>void Heap(int *, int );void Init(int *, int);void In(int *, int);void Init(int *A, int n){

int i;printf("\n Tao lap day so:");for (i=0; i<n;i++){

A[i]=random(1000);printf("%5d",A[i]);

}delay(1000);

}void Heap(int *A, int n) {

int k,x,s,f,ivalue;for(k=1;k<n;k++){

x=A[k];s=k; f=(s-1)/2;while(s>0 && A[f]<x){

A[s]=A[f];s=f; f=(s-1)/2;

14

Page 15: Heap Sort

Nguyenjjdsds êfefefe

}A[s]=x;

}for(k=n-1;k>0;k--){

ivalue=A[k];A[k]=A[0];f=0;if(k==1)

s=-1;else

s=1;if(k>2 && A[2]>A[1])

s=2;while(s>=0 && ivalue<A[s]){

A[f]=A[s];f=s;s=2*f +1;if (s+1<=k-1 && A[s]<A[s+1])

s=s+1;if (s>k-1)

s=-1;}A[f]=ivalue;

}}

void In(int *A, int n){register int i;for(i=0;i<n;i++)

printf("%5d",A[i]);delay(1000);

}void main(void){

int *A,n;clrscr();printf("\n Nhap n="); scanf("%d",&n);A=(int *) malloc(n*sizeof(int));Init(A,n);Heap(A,n);printf("\n");In(A,n);getch();free(A);

}

15

Page 16: Heap Sort

Nguyenjjdsds êfefefe

/* Chuong trinh minh hoa Heap Sort */#include <stdio.h>#include <stdlib.h>#include <conio.h>#define MAXLIST 200#define TRUE 1#define FALSE 0int nodes[MAXLIST];void heapsort(int nodes[], int n){int k, x, s, f, ivalue;// chuyen danh sach nodes[] thanh heapfor(k = 1; k < n; k++){x = nodes[k]; // Nut can them vao heap// tac vu insert(nodes[], k, x)s = k; // s la nut conf = (s-1)/2; // f la nut chawhile(s > 0 && nodes[f] < x){nodes[s] = nodes[f]; // keo nut < x xuong mot mucs = f;f = (s-1)/2;}nodes[s] = x; // dien nut x vao vi tri phu hop}// lan luot xoa nodes[0] tren heap, copy no ve vi tri thich hop tren dsfor(k = n-1; k > 0; k--){// tac vu removeroot(nodes[], k+1)ivalue = nodes[k]; // ivalue la nut hien tai o vi tri knodes[k] = nodes[0]; // chuyen nut goc xuong vi tri kf = 0; // f la nut cha, s la nut con lon hon// s = largeson(0, k-1)if(k == 1)s = -1;elses = 1;if(k > 2 && nodes[2] > nodes[1])s = 2;while(s >= 0 && ivalue < nodes[s]){nodes[f] = nodes[s]; // doi nut con lon hon len 1 mucf = s;// s = largeson(f, k-1)s = 2*f+1;if(s+1 <= k-1 && nodes[s] < nodes[s+1])s = s+1;if(s > k-1)s = -1;}nodes[f] = ivalue;

16

Page 17: Heap Sort

Nguyenjjdsds êfefefe

}}// Chuong trinh chinhvoid main(){int i, chucnang;char c;clrscr();do{// menu chinh cua chuong trinhprintf("\n\n\tHEAPSORT");printf("\n\nCac chuc nang cua chuong trinh:\n");printf(" 1: Tao danh sach voi %d so ngau nhien\n", MAXLIST);printf(" 2: Heap Sort\n");printf(" 3: Duyet danh sach\n");printf(" 0: Ket thuc chuong trinh\n");printf("Chuc nang ban chon: ");scanf("%d", &chucnang);switch(chucnang){case 1:{for(i = 0; i < MAXLIST; i++)nodes[i] = random(1000);printf("\nDa tao xong danh sach voi %d so ngau nhien", MAXLIST);break;}case 2:{heapsort(nodes, MAXLIST);printf("\nDa sap xep xong danh sach theo giai thuat Heap Sort");break;}case 3:{printf("\nDUYET DANH SACH:\n");for(i = 0; i < MAXLIST; i++)printf("%4d", nodes[i]);break;}}} while(chucnang != 0);}

17