public static void Merge(AValue[] A, int iBegin, int iMiddle, int iEnd, AValue[] B) { #region algorithm //TopDownMerge(A[], iBegin, iMiddle, iEnd, B[]) //{ // i0 = iBegin, i1 = iMiddle; // // // While there are elements in the left or right runs // for (j = iBegin; j < iEnd; j++) { // // If left run head exists and is <= existing right run head. // if (i0 < iMiddle && (i1 >= iEnd || A[i0] <= A[i1])) // B[j] = A[i0++]; // Increment i0 after using it as an index. // else // B[j] = A[i1++]; // Increment i1 after using it as an index. // } //} #endregion //# before ResetDataCanvas(iBegin, 0, iEnd, 99); // reset data canvas - for visualization DrawC(iBegin, iEnd, Pens.Green, true); // draw C canvas - for visualization //# do merge int i0 = iBegin; int i1 = iMiddle + 1; int j = iBegin; while (i0 <= iMiddle && i1 <= iEnd) { if (A[i0] <= A[i1]) { DrawC(i0, Pens.LightGray); // reset C - for visualization // B[j++] = A[i0++]; Update(B, j++, A[i0++]); } else { DrawC(i1, Pens.LightGray); // reset C - for visualization // B[j++] = A[i1++]; Update(B, j++, A[i1++]); } } while (i0 <= iMiddle) { DrawC(i0, Pens.LightGray); // reset C - for visualization. //B[j++] = A[i0++]; Update(B, j++, A[i0++]); } while (i1 <= iEnd) { DrawC(i1, Pens.LightGray); // reset C - for visualization. //B[j++] = A[i1++]; Update(B, j++, A[i1++]); } }
/// <summary> /// 泡沫排序法 /// </summary> public static void BubbleSort(AValue[] datas) { for (int i = 0; i < datas.Length - 1; i++) for (int j = i + 1; j < datas.Length; j++) if (datas[i] > datas[j]) // compare Exchange(datas, i, j); // swap }
public static void MaxHeapify(AValue[] datas, int heap_size, int index) { #region algorithm // Max-Heapify (A, i ) //1 l <- Left (i ) //2 r <- Right(i ) //3 if l ≤ heap-size[A] and A[l] > A[i ] //4 then largest <- l //5 else largest <- i //6 if r ≤ heap-size[A] and A[r] > A[largest] //7 then largest <- r //8 if largest <> i //9 then exchange A[i] <-> A[largest] //10 Max-Heapify (A, largest) #endregion //int heap_size = datas.Length; int l = HeapLeft(index); int r = HeapRight(index); int largest = index; if (l < heap_size && datas[l] > datas[largest]) largest = l; if (r < heap_size && datas[r] > datas[largest]) largest = r; if (largest != index) { Exchange(datas, index, largest); // exchange A[i] <-> A[largest] MaxHeapify(datas, heap_size, largest); } }
/// <summary> /// 選擇排序法 /// </summary> public static void SelectionSort(AValue[] datas) { #region algorithm //Function selectionSort(Type data[1..n]) // Index i, j, max --- or min // For i from 1 to n do // max = i // For j from i + 1 to n do // If data[j] > data[max] then // max = j // // Exchange data[i] and data[max] //End #endregion //# Index i, j, max --- or min int minIndex; for (int i = 0; i < datas.Length; i++) { minIndex = i; for (int j = i + 1; j < datas.Length; j++) if (datas[j] < datas[minIndex]) // compare minIndex = j; //# Exchange data[i] and data[min] if(i != minIndex) Exchange(datas, i, minIndex); } }
public static void TopDownSplitMerge(AValue[] datas, int iBegin, int iEnd, AValue[] mergedDatas) { #region algorithm //TopDownSplitMerge(A[], iBegin, iEnd, B[]) //{ // if(iEnd - iBegin < 2) // if run size == 1 // return; // consider it sorted // // recursively split runs into two halves until run size == 1, // // then merge them and return back up the call chain // iMiddle = (iEnd + iBegin) / 2; // iMiddle = mid point // TopDownSplitMerge(A, iBegin, iMiddle, B); // split / merge left half // TopDownSplitMerge(A, iMiddle, iEnd, B); // split / merge right half // TopDownMerge(A, iBegin, iMiddle, iEnd, B); // merge the two half runs // CopyArray(B, iBegin, iEnd, A); // copy the merged runs back to A //} #endregion //Debug.WriteLine(string.Format("TopDownSplitMerge iBegin ~ iEnd : {0} ~ {1}", iBegin, iEnd)); if (iEnd <= iBegin) // consider it sorted. return; int iMiddle = (iEnd + iBegin) / 2; TopDownSplitMerge(datas, iBegin, iMiddle, mergedDatas); // split / merge left half TopDownSplitMerge(datas, iMiddle + 1, iEnd, mergedDatas); // split / merge right half Merge(datas, iBegin, iMiddle, iEnd, mergedDatas); CopyArray(mergedDatas, iBegin, iEnd, datas); // // copy the merged runs back to A }
public static void QuickSortRand(AValue[] datas, int p, int r) { #region algorithm //RANDOMIZED_QUICKSORT(A,p,r) //1 if p < r then //2 q <- RANDOMIZED_PARTITION(A,p,r) //3 RANDOMIZED_QUICKSORT(A, p, q-1) //4 RANDOMIZED_QUICKSORT(A,q+1,r) #endregion if (p < r) { int q = QuickSortRandPartition(datas, p, r); QuickSortRand(datas, p, q - 1); QuickSortRand(datas, q + 1, r); } }
/// <summary> /// 基數排序法 /// </summary> public static void RadixSort(AValue[] datas) { #region algorithm //#define MAX 20 //#define SHOWPASS //#define BASE 10 //void radixsort(int *a, int n) //{ // int i, b[MAX], m = a[0], exp = 1; // for (i = 1; i < n; i++) // { // if (a[i] > m) // m = a[i]; // } // // while (m / exp > 0) // { // int bucket[BASE] ={ 0 }; // for (i = 0; i < n; i++) // bucket[(a[i] / exp) % BASE]++; // for (i = 1; i < BASE; i++) // bucket[i] += bucket[i - 1]; // for (i = n - 1; i >= 0; i--) // b[--bucket[(a[i] / exp) % BASE]] = a[i]; // for (i = 0; i < n; i++) // a[i] = b[i]; // exp *= BASE; // // #ifdef SHOWPASS // printf("\nPASS : "); // print(a, n); // #endif // } //} #endregion //## parameters const int BASE = 10; //## get max value int m = 99; // datas.Max(); // with bucket sort int n = datas.Length; AValue[] B = new AValue[n]; // as sorted datas. int exp = 1; while (m / exp > 0) { //## bucket sort int[] bucket = new int[BASE]; // visualize bucket. AValueEx.ResetCountCanvas(); for (int i = 0; i < n; i++) { //# bucket[(datas[i] / exp) % BASE]++; int bx = (datas[i].Value / exp) % BASE; // bucket index. //bucket[bx]++; UpdateC(bucket, bx, bucket[bx] + 1); } for (int i = 1; i < BASE; i++) { //bucket[i] += bucket[i-1]; UpdateC(bucket, i, bucket[i] + bucket[i-1]); } //# put to calculated index. AValueEx.ResetDataCanvas(); // for visualization for (int i = n - 1; i >= 0; i--) { // b[--bucket[(datas[i] / exp) % BASE]] = datas[i]; int bx = (datas[i].Value / exp) % BASE; int bi = --bucket[bx]; //B[bi] = datas[i]; Update(B, bi, datas[i]); // for visualization AValueEx.DrawC(bx, bucket[bx]); // 變化太微量,看不出變化 } // copy back for next round sorting AValueEx.CopyArray(B, 0, n - 1, datas); // next round. exp *= BASE; } }
public static void DrawData(AValue[] datas, int index) { Pen pen = new Pen(MapColor(datas[index].MoveTimes)); DrawData(datas, index, true, pen); }
public static void DrawDatas(AValue[] datas, Pen pen) { // reset data canvas ResetDataCanvas(0, 0, 99, 99); // draw one by one for (int i = 0; i < datas.Length; i++) Form1._g.DrawLine(pen, i, datas[i].Value, i, 0); }
public static void DrawData(AValue[] datas, int index, bool redrawBackground, Pen pen) { // redraw background if (redrawBackground) Form1._g.DrawLine(Pens.LightGray, index, 99, index, 0); // draw data Form1._g.DrawLine(pen, index, datas[index].Value, index, 0); }
public static void DrawData(AValue[] datas, int index, bool redrawBackground) { Pen pen = new Pen(MapColor(datas[index].MoveTimes)); DrawData(datas, index, redrawBackground, pen); }
/// <summary> /// 計數排序法 /// </summary> public static void CountingSort(AValue[] datas) { #region algorithm //CountingSort(A,B,k) //1.for i <- 0 to k //2. do C[i] <- 0 //3.for j <- 1 to length[A] //4. do C[A[j]] <- C[A[j]]+1 //5. // C[i] now contains the number of elements equal to i. //6.for i <- 1 to k //7. do C[i] <- C[i] + C[i-1] //8. // C[i] now contains the number of elements less than or equal to i. //9. for j <- length[A] downto 1 //10. do B[C[A[j]]] <- A[j] //11 C[A[j]] <- C[A[j]] - 1 #endregion //# duplation as A in place of datas[]. and let datas[] as B; AValue[] A = new AValue[datas.Length]; CopyArray(datas, 0, datas.Length -1, A); //## BEGIN to do counting sort. //# step 1,2. int[] C = new int[A.Length]; for (int i = 0; i < C.Length; i++) // k == length[A], in this case. C[i] = 0; // do C[i] <- 0 // show C - for visualizaton. AValueEx.ResetCountCanvas(); //# step 3,4. for (int i = 0; i < A.Length; i++) { // C[A[i]]++; int ci = A[i].Value; // C index UpdateC(C, ci, C[ci]+1); } //# step 6,7. for (int i = 1; i < C.Length; i++) { // C[i] = C[i] + C[i-1]; UpdateC(C, i, C[i] + C[i - 1]); } //# step 8,9,10. AValueEx.ResetDataCanvas(); // for visualization for (int i = A.Length - 1; i >= 0; i--) { //# B[C[A[j]]] <- A[j] // 'datas' as B int di = C[A[i].Value] - 1; // zero base array. Update(datas, di, A[i]); // //datas[di] = A[i]; //# C[A[j]] <- C[A[j]] - 1 int ci = A[i].Value; C[ci]--; // visualize C AValueEx.DrawC(ci, C[ci]); // 變化太微量,看不出變化 } }
public static void CopyArray(AValue[] dataFrom, int iBegin, int iEnd, AValue[] dataTo) { for (int i = iBegin; i <= iEnd; i++) dataTo[i] = dataFrom[i]; }
public static void BuildMaxHeap(AValue[] datas) { #region algorithm //Build-Max-Heap(A) //1 heap-size[A] <- length[A] //2 for i <- floor(length[A]/2) downto 1 --- 1 base array //3 do Max-Heapify(A, i) #endregion int heap_size = datas.Length; for (int i = (datas.Length - 1) / 2; i >= 0; i--) //--- 0 base array MaxHeapify(datas, heap_size, i); }
/// <summary> /// 快速排序法 /// </summary> public static void QuickSort(AValue[] datas, int p, int r) { //Function QuickSort(A, p, r) // IF p < r Then // q = PARTITION(A, p, r) // QuickSort(A, p, q-1) // QuickSort(A, q+1, r) //End if (p < r) { int q = QuickSortPartition(datas, p, r); QuickSort(datas, p, q - 1); QuickSort(datas, q + 1, r); } }
/// <summary> /// 複製數據列並重製狀態 /// </summary> public static AValue[] DuplicateDatas(AValue[] datas) { AValue[] A = new AValue[datas.Length]; for (int i = 0; i < datas.Length; i++) A[i] = new AValue(datas[i].Value); // new AValue state is reset. // reset state _compareCount = 0; _exchangeCount = 0; _updateCount = 0; _countingCount = 0; return A; }
public static int QuickSortPartition(AValue[] datas, int p, int r) { // Partition subarray A[p..r] by the following procedure: //1 x <- A[r] //2 i <- p – 1 //3 for j <- p to r -1 //4 do if A[j] ≤ x //5 then i <- i + 1 //6 exchange A[i] <-> A[j] //7 exchange A[i +1] <-> A[r] //8 return i +1 AValue x = datas[r]; int i = p - 1; for (int j = p; j < r; j++) if (datas[j] < x) { // i = i + 1; i++; // exchange A[i]<->A[j] Exchange(datas, i, j); } // exchange A[i+1] <-> A[r] i++; if(i != r) Exchange(datas, i, r); return i; }
/* ====== ACTION ====== */ public static void Exchange(AValue[] datas, int i, int j) { // exchange AValue tmp = datas[i]; datas[i] = datas[j]; datas[i].IncreaseMoveTimes(); datas[j] = tmp; datas[j].IncreaseMoveTimes(); // visual exchange DrawData(datas, i); DrawData(datas, j); // counting _exchangeCount++; // wait a short time Thread.Sleep(Form1._sleepTimespan); }
public static int QuickSortRandPartition(AValue[] datas, int p, int r) { #region algorithm //RANDOMIZED_PARTITION(A,p,r) //1 i <- RANDOM(p,r) //2 exchange A[r]<->A[i] //3 return PARTITION(A,p,r) #endregion // randomize Random rand = new Random(); int i = p + rand.Next(r - p); Exchange(datas, r, i); // exchange A[r]<->A[i] return QuickSortPartition(datas, p, r); }
/// <summary> /// 產生亂數數列或排序、反排序數列。 /// </summary> /// <param name="mode">0.randoom; 1.sorted; 2.reverse sorted</param> /// <returns></returns> public static AValue[] GenRandDatas(int mode) { const int size = 100; //# init. int array AValue[] datas = new AValue[size]; for (int i = 0; i < size; i++) datas[i] = new AValue(mode == 2 ? size - 1 - i : i); // 0 ~ 99 if (mode == 1 || mode == 2) return datas; // randomize Random r = new Random(); for (int i = 0; i < size; i++) { int i1 = r.Next(size); int i2 = r.Next(size); // swap AValue tmp = datas[i1]; datas[i1] = datas[i2]; datas[i2] = tmp; } return datas; }
public static void ResetDatasState(AValue[] datas) { for (int i = 0; i < datas.Length; i++) datas[i].ResetState(); // reset state _compareCount = 0; _exchangeCount = 0; _updateCount = 0; _countingCount = 0; }
/// <summary> /// 堆積排序法 /// </summary> public static void HeapSort(AValue[] datas) { #region algorithm // Heapsort(A) //1 Build-Max-Heap(A) //2 for i <- length[A] down to 2 //3 do exchange A[1]<->A[i] --- 1 base array //4 heap-size[A] <- heap-size[A] -1 //5 Max-Heapify(A,1) #endregion BuildMaxHeap(datas); int heap_size = datas.Length; for (int i = datas.Length - 1; i >= 1; i--) { Exchange(datas, i, 0); // 0 base array heap_size--; MaxHeapify(datas, heap_size, 0); } }
/// <summary> /// 合併排序法 /// </summary> public static void TopDownMergeSort(AValue[] datas) { #region algorithm //TopDownMergeSort(A[], B[], n) //{ // TopDownSplitMerge(A, 0, n, B); //} #endregion AValue[] mergedDatas = new AValue[datas.Length]; TopDownSplitMerge(datas, 0, datas.Length - 1, mergedDatas); }
/// <summary> /// 插入排序法 /// </summary> public static void InsertionSort(AValue[] datas) { //從未排序數列取出一元素。 //由後往前和已排序數列元素比較,直到遇到不大於自己的元素並插入此元素之後;若都沒有則插入在最前面。 //重複以上動作直到未排序數列全部處理完成。 AValue[] sortedDatas = new AValue[datas.Length]; for (int i = 0; i < datas.Length; i++) { // 取出 AValue c = datas[i]; // 比較 int insertIndex = i; for (; insertIndex > 0 && sortedDatas[insertIndex - 1] > c; insertIndex--) ; // compare // 插入-shift for (int j = i; j > insertIndex; j--) { Update(sortedDatas, j, sortedDatas[j-1]); } // 插入-new Update(sortedDatas, insertIndex, c, Pens.Red); } // copy back CopyArray(sortedDatas, 0, sortedDatas.Length - 1, datas); }
public static void Update(AValue[] datas, int index, AValue value, Pen pen) { // update value datas[index] = value; datas[index].IncreaseMoveTimes(); // visual update DrawData(datas, index, true, pen); // counting _updateCount++; // wait a short time Thread.Sleep(Form1._sleepTimespan); }
/// <summary> /// 下上合併排序法 /// </summary> /// <param name="datas"></param> public static void BottomUpMergeSort(AValue[] datas) { /* let 'datas' as array A */ /* let 'mergedDatas' as array B*/ AValue[] mergedDatas = new AValue[datas.Length]; /* Each 1-element run in A is already "sorted". */ /* Make successively longer sorted runs of length 2, 4, 8, 16... until whole array is sorted. */ int n = datas.Length - 1; for (int width = 1; width <= n; width = 2 * width) { /* Array A is full of runs of length width. */ for (int i = 0; i <= n; i = i + 2 * width) { /* Merge two runs: A[i:i+width-1] and A[i+width:i+2*width-1] to B[] */ /* or copy A[i:n-1] to B[] ( if(i+width >= n) ) */ Merge(datas, i, Min(i + width - 1, n), Min(i + 2 * width - 1, n), mergedDatas); } /* Now work array B is full of runs of length 2*width. */ /* Copy array B to array A for next iteration. */ /* A more efficient implementation would swap the roles of A and B */ CopyArray(mergedDatas, 0, n, datas); /* Now array A is full of runs of length 2*width. */ } }