Jul 2

玩ACM时用到的堆排序算法 (C和Java) 不指定

Posted by bbscool at 21:59 | 网海拾贝 | 评论(0) | 阅读(798) | 转自 本站原创 | |
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

(1)用大根堆排序的基本思想
① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
③ 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
   ……
直到无序区只有一个元素为止。

(2)大根堆排序算法的基本操作:
① 初始化操作:将R[1..n]构造为初始堆;
② 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
 注意:
①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。
②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻,堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。

(3)堆排序的算法:
 void HeapSort(SeqIAst R)
  { //对R[1..n]进行堆排序,不妨用R[0]做暂存单元
   int i;
   BuildHeap(R); //将R[1-n]建成初始堆
   for(i=n;i>1;i--){ //对当前无序区R[1..i]进行堆排序,共做n-1趟。
     R[0]=R[1];R[1]=R[i];R[i]=R[0]; //将堆顶和堆中最后一个记录交换
     Heapify(R,1,i-1); //将R[1..i-1]重新调整为堆,仅有R[1]可能违反堆性质
    } //endfor
  } //HeapSort

Flash演示动画:




Java实现:

01 package algorithms;
02
03 /**
04 * @author yovn
05 *
06 */
07 public class HeapSorter<E extends Comparable<E>> extends Sorter<E>  {
08
09    /* (non-Javadoc)
10     * @see algorithms.Sorter#sort(E[], int, int)
11     */
12    @Override
13    public void sort(E[] array, int from, int len) {
14        build_heap(array,from,len);
15
16        for(int i=0;i<len;i++)
17        {
18            //swap max value to the (len-i)-th position
19            swap(array,from,from+len-1-i);
20            shift_down(array,from,len-1-i,0);//always shiftDown from 0
21        }
22    }
23
24    private final void build_heap(E[] array, int from, int len) {
25        int pos=(len-1)/2;//we start from (len-1)/2, because branch's node +1=leaf's node, and all leaf node is already a heap
26        for(int i=pos;i>=0;i--)
27        {
28            shift_down(array,from,len,i);
29        }
30        
31    }
32    
33    private final void shift_down(E[] array,int from, int len, int pos)
34    {
35        
36        E tmp=array[from+pos];
37        int index=pos*2+1;//use left child
38        while(index<len)//until no child
39        {
40            if(index+1<len&&array[from+index].compareTo(array[from+index+1])<0)//right child is bigger
41            {
42                index+=1;//switch to right child
43            }
44            if(tmp.compareTo(array[from+index])<0)
45            {
46                array[from+pos]=array[from+index];
47                pos=index;
48                index=pos*2+1;
49                
50            }
51            else
52            {
53                break;
54            }
55            
56        }
57        array[from+pos]=tmp;
58            
59    }
60
61    
62 }

C语言实现:
01 #define Left(i)        ((i) << 1)        
02 #define Right(i)    (((i) << 1) + 1)
03 void heapsort(int a[], int heapsize);
04 void maxheapify(int a[], int i, int heapsize);
05 void swap(int *x, int *y);
06 main(){
07       int ts[5]={21,25,11,24,77};
08       heapsort(ts,n1);
09 }
10 void heapsort(int a[], int heapsize)
11 {
12    int i;
13
14    for (i = heapsize / 2; i >= 1; i--)
15        maxheapify(a, i, heapsize);        
16
17    for (i = heapsize; i >= 2; i--)
18        {
19        swap(&a[1], &a[i]);
20        heapsize--;
21        maxheapify(a, 1, heapsize);
22    }
23 }
24 void maxheapify(int a[], int i, int heapsize)
25 {
26    int largest, left, right;
27
28    left = Left(i);
29    right = Right(i);
30
31    if (left <= heapsize && a[left] > a[i])
32        largest = left;
33    else
34        largest = i;
35    if (right <= heapsize && a[right] > a[largest])
36        largest = right;
37
38    if (largest != i)
39    {
40        swap(&a[i], &a[largest]);
41        maxheapify(a, largest, heapsize);
42    }
43
44    return;
45 }
46 void swap(int *x, int *y)
47 {
48    int temp;
49
50    temp = *x;
51    *x = *y;
52    *y = temp;
53 }


Tags: ,
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]