泛型堆排序
介绍
堆排序是排序算法一种,适用于最小和最大的元素取值,以下情况适合堆排序
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;