泛型堆排序

介绍

堆排序是排序算法一种,适用于最小和最大的元素取值,以下情况适合堆排序

1. 优先级队列,总要得到最优先的元素

堆排序的过程, 例子队列插入顺序 List.Add(10) ... ,6,3,5,7,2

A. 建立二叉堆

       [10] -> [10][6] CheckParent(1) // 1 代表当前位置

       function CheckParent(pos):

            if(pos < 1) return;

          // 得到他的父亲节点, 他和父亲的关系根据索引值存储在数组中

            parent = (pos-1) /2 ;

          // 如果比父亲优先级高,交换, 如果还比父亲的父亲还高,则继续交换        

           while(Compare(pos, parent)) :

                     Swap(pos, parent);

                     // 重新计算pos和parent的值

/* --------------------------------------------------------------------------

例如: [6][10][5] 此时插入3, 则先比较3和他的父亲10, 交换3,10,则变成了 [6][3][5][10], 继续比较3和父亲6的大小,继续交换[6][3],最终结果为[3][6][5][10]

----------------------------------------------------------------------------*/

B. 得到最优元素

得到堆顶元素即数组第一个元素,删除该元素,将数组最后一个元素放到最末,再比较他和儿子之间的关系,类似 CheckParent, 这样堆顶部永远是优先级最高的元素。

代码

如下(有点乱):

   1: public class BinaryHeap<T> where T : IComparable
   2:    {
   3:        protected List<T> MyList;
   4:  
   5:        public BinaryHeap()
   6:        {
   7:            MyList = new List<T>();
   8:        }
   9:        public BinaryHeap(int capbility)
  10:        {
  11:            MyList = new List<T>(capbility);
  12:        }
  13:  
  14:        public bool IsEmpty
  15:        {
  16:            get {
  17:                return MyList.Count < 1;
  18:            }
  19:        }
  20:  
  21:        public T GetTop()
  22:        {
  23:            if (MyList.Count < 1) throw new IndexOutOfRangeException();
  24:            T t = MyList[0];
  25:            MyList[0] = MyList[MyList.Count - 1];
  26:            MyList.RemoveAt(MyList.Count - 1);
  27:  
  28:            CheckChildren(0);
  29:  
  30:            return t;
  31:        }
  32:  
  33:        public void Add(T t)
  34:        {
  35:            MyList.Add(t);
  36:  
  37:            CheckParent(MyList.Count - 1);
  38:        }
  39:  
  40:  
  41:        public void Clear()
  42:        {
  43:            MyList.Clear();
  44:        }
  45:  
  46:        public bool Contains(T item)
  47:        {
  48:            return MyList.Contains(item);
  49:        }
  50:  
  51:        public void CopyTo(T[] array, int arrayIndex)
  52:        {
  53:            MyList.CopyTo(array, arrayIndex);
  54:        }
  55:  
  56:        /// <summary>
  57:        /// 比较和父亲关系
  58:        ///     3
  59:        ///    / \
  60:        ///   2   4
  61:        /// </summary>
  62:        /// <param name="pos"></param>
  63:        private void CheckParent(int pos)
  64:        {
  65:            if (pos < 0 || pos > MyList.Count - 1) throw new IndexOutOfRangeException();
  66:  
  67:            int parent = (int)(pos -1)/2;
  68:  
  69:            while (pos != 0 && parent != -1)
  70:            {
  71:                if (MyList[parent].CompareTo(MyList[pos]) > 0)
  72:                {
  73:                    Swap(pos,parent);
  74:                    pos = parent;
  75:                    parent = (int)((pos - 1) / 2);
  76:                }
  77:                else break;
  78:            }
  79:        }
  80:  
  81:        private void CheckChildren(int pos)
  82:        {
  83:            if (pos < 0) throw new IndexOutOfRangeException();
  84:  
  85:            int left = -1, right = -1;
  86:            left = (pos + 1) * 2 - 1;
  87:            right = left + 1;
  88:  
  89:            //int childIndex = -1;
  90:            while (left <= MyList.Count-1)
  91:            {
  92:                bool hasFound = false;
  93:                right = left + 1;
  94:                if (right >= MyList.Count) { right = left; left--; }
  95:                if (MyList[pos].CompareTo(MyList[left]) > 0 && MyList[left].CompareTo(MyList[right]) < 0)
  96:                {
  97:                    Swap(pos, left);
  98:                    pos = left;
  99:                    hasFound = true;
 100:                } 
 101:                if (MyList[pos].CompareTo(MyList[right]) > 0 && MyList[right].CompareTo(MyList[left]) < 0)
 102:                {
 103:                    Swap(pos, right);
 104:                    pos = right;
 105:                    hasFound = true;
 106:                }
 107:  
 108:                if (!hasFound) return;
 109:  
 110:                left = (pos + 1) * 2 - 1;
 111:                
 112:  
 113:            }
 114:        }
 115:  
 116:        private void Swap(int x, int y)
 117:        {
 118:            T z = MyList[x];
 119:            MyList[x] = MyList[y];
 120:            MyList[y] = z;
 121:        
 122:            
 123:        }
 124:  
 125:        public int Count
 126:        {
 127:            get { return MyList.Count; }
 128:        }
 129:  
 130:        public bool IsReadOnly
 131:        {
 132:            get { return false; }
 133:        }
 134:  
 135:        public bool Remove(T item)
 136:        {
 137:            return MyList.Remove(item);
 138:        }
 139:  
 140:  
 141:        public IEnumerator<T> GetEnumerator()
 142:        {
 143:            return MyList.GetEnumerator();
 144:        }
 145:  
 146:    }

测试代码:

   1: BinaryHeap<int> heap = new BinaryHeap<int>();
   2:            heap.Add(10);
   3:            heap.Add(6);
   4:            heap.Add(3);
   5:            heap.Add(5);
   6:            heap.Add(7);
   7:            heap.Add(2);
   8:            while (!heap.IsEmpty)
   9:                Console.WriteLine(heap.GetTop());
  10:  
  11:            Console.Read();
  12:            return;

测试结果:

image

posted on 2008-07-16 22:40  xwang  阅读(530)  评论(2编辑  收藏  举报

导航