首页 > 代码库 > 算法案例
算法案例
1、冒泡(Bubble)
7 5 2 1 5 9
5 7 2 1 5 9
5 2 7 1 5 9
5 2 1 7 5 9
5 2 1 5 7 9
2 5 1 5 7 9
2 1 5 5 7 9
2 1 5 5 7 9
1 2 5 5 7 9
public static void BubbleSort(int[] a) { int n = a.Length - 1;//个数 int i, j;//用于控制循环 int tmp;//中间变量 bool isChange;//记录冒泡一轮下来是否发生交换(如果没有发生交换证明已排好序) for (i = 0; i < n; i++) { isChange = false; for (j = 0; j < n - i; j++)//每轮冒泡过后要对比的数就少一个 { if (a[j] > a[j + 1])//大的数向上冒 { tmp = a[j]; a[j] = a[j + 1]; a[j + 1] = tmp; isChange = true; } } if (!isChange) { return; } } return; }
2、直接插入(Insert)
7 5 2 1 5 9
5 7 2 1 5 9
2 5 7 1 5 9
1 2 5 7 5 9
1 2 5 5 7 9
public static void InsertSort(int[] a) { int n = a.Length; for (int i = 1; i < n; i++)//循环从第二个数组元素开始,因为arr[0]作为最初已排序部分 { int temp = a[i];//temp标记为未排序第一个元素 int j = i - 1; while (j >= 0 && a[j] > temp)//将temp与已排序元素从小到大比较,寻找temp应插入的位置 { a[j + 1] = a[j]; j--; } a[j + 1] = temp; } }
3、直接选择(Select)
7 5 2 1 5 9
1 5 2 7 5 9
1 2 5 7 5 9
1 2 5 7 5 9
1 2 5 5 7 9
public static void SelectSort(int[] a) { int n = a.Length;//个数 int i, j; int tmp; int b; for (i = 0; i < n - 1; i++) { tmp = i; for (j = i + 1; j < n; j++) { if (a[tmp] > a[j])//每轮找到最小的元素 tmp = j; } if (i != tmp) { b = a[tmp]; a[tmp] = a[i]; a[i] = b; } } }
4、快速(Quick)
7 5 2 1 5 9
5 2 1 5 7 9
2 1 5 5 7 9
1 2 5 5 7 9
public static void QuickSort(int[] a, int low, int high) { if (low < high) { // ↓ ↓ int point = MovePart(a, low, high);// 5 6 2 1 4 9 4 1 2 5 6 9 QuickSort(a, low, point); QuickSort(a, point + 1, high); } } public static int MovePart(int[] a, int partLow, int partHigh) { int pivotP = partLow;//记住枢纽位置 while (partLow < partHigh) { while (partLow < partHigh && a[partHigh] >= a[pivotP])//右往左找第一个小于pivot的数 { partHigh--; } Swap(a, pivotP, partHigh); pivotP = partHigh; while (partLow < partHigh && a[partLow] <= a[pivotP])//左往右找第一个大于prvot的数 { partLow++; } Swap(a, partLow, pivotP); pivotP = partLow; } return pivotP;//返回分割点 } public static void Swap(int[] a, int pivotP, int swapP) { int t; t = a[pivotP]; a[pivotP] = a[swapP]; a[swapP] = t; }
5、希尔(Shell)
7 5 2 1 5 9
7 5 2 1 5 9
7 5 2 1 5 9
5 7 2 1 5 9
2 5 7 1 5 9
2 5 7 1 5 9
1 2 5 7 5 9
1 2 5 5 7 9
public static void ShellSort(int[] a) { int n = a.Length; for (int incr = 3; incr > 0; incr--)//增量递减,增量据说以9 5 3 1最优(各种大牛到现在都没有定论),此处为3 2 1 { for (int L = 0; L < (n - 1) / incr; L++)//重复分成的每个子列表 { for (int i = L + incr; i < n; i += incr)//对每个子列表应用插入排序 { int temp = a[i]; int j = i - incr; while (j >= 0 && a[j] > temp) { a[j + incr] = a[j]; j -= incr; } a[j + incr] = temp; } } } }
6、归并(Merge)
7 5 2 1 5 9
7 5 2 1 5 9
7 5 2 1 5 9
7 2 5 1 5 9
2 5 7 1 5 9
1 2 5 5 7 9
public static void Merge(int[] a, int low, int center, int high) { if (low >= high) return; int m = center - low + 1; int n = high - center; int[] L = new int[m]; int[] R = new int[n]; int i, j, k; for (i = 0; i < m; ++i) L[i] = a[low + i];//取得左边数 for (i = 0; i < n; ++i) R[i] = a[low + i + m];//取得右边数 for (i = 0, j = 0, k = low; i < m && j < n; ++k) { if (L[i] > R[j])//从L、R两边选比较小的数放进a,直到一边放完 { a[k] = R[j]; j++; } else { a[k] = L[i]; i++; } } while (i < m)//如果是L没放完,把L剩余的数放进a { a[k] = L[i]; k++; i++; } while (j < n)//如果是R没放完,把R剩余的数放进a { a[k] = R[j]; k++; j++; } } public static void MergeSort(int[] a, int low, int high) { int center; if (low < high) { center = (low + high) / 2; MergeSort(a, low, center); MergeSort(a, center + 1, high); Merge(a, low, center, high); } }
7、堆(Heap)
7 5 2 1 5 9
7
/ \
5 2
/ \ / \
1 5 9
9
/ \
5 7
/ \ / \
1 5 2
/// <summary> /// 堆排序,此处为倒序,要升序,请使用大二叉堆,或对数组进行首尾交换 /// </summary> /// <param name="a"></param> /// <param name="n"></param> public static void HeapSort(int[] a, int n) { MakeMinHeap(a, n);//将数组建立成最小堆 for (int i = n - 1; i >= 1; i--) { Swap(a, i, 0);//把该论得到的最小数排到末尾已拍好序的的数前 MinHeapFixDown(a, 0, i);//排除末尾拍好序的的数得出子二叉堆,在作调整得出新的二叉堆,root又为最小的数 } } /// <summary> /// 新加入叶子结点 /// </summary> /// <param name="a"></param> /// <param name="leafPoint">叶子结点所在位置</param> public static void MinHeapAddPoint(int[] a, int leafPoint)//以叶子结点,叶子结点的父结点,叶子结点的爷结点...为一组进行直接插入 { int fartherPoint, temp,currentPornt; temp = a[leafPoint]; currentPornt = leafPoint;//记录当前节点位置 fartherPoint = (leafPoint - 1) / 2; //父结点 while (a[fartherPoint] > a[currentPornt]&& currentPornt!=0) { a[currentPornt] = a[fartherPoint]; currentPornt = fartherPoint; fartherPoint = (currentPornt - 1) / 2;//父结点为的位置为 (currentPoint - 1) / 2 } a[currentPornt] = temp; } /// <summary> /// 在最小堆中加入新的数据num (从叶子结点(数组尾)插入) /// </summary> /// <param name="a"></param> /// <param name="n">新增结点位置(数组结尾位置+1 即 数组长度)</param> /// <param name="num">新增结点值</param> public static void MinHeapAddNumber(int[] a, int n, int num) { a[n] = num; MinHeapAddPoint(a, n); } /// <summary> /// 删除跟结点(将最后的结点a[n]放到根节点a[0]的位置)后的堆调整 /// 从i整节点向下开始调整,n为节点总数, 从0开始计算 i节点的子节点为 2*i+1, 2*i+2 /// </summary> /// <param name="a">数组</param> /// <param name="fatherPoint">要调整的位置</param> /// <param name="n">二叉堆的长度(要调整到数组的那个位置)</param> public static void MinHeapFixDown(int[] a, int fatherPoint, int n) { int sonPoint, temp; temp = a[fatherPoint]; sonPoint = 2 * fatherPoint + 1;//左子结点,右子节点为sonPoint+1 子节点为 2*i+1, 2*i+2 while (sonPoint <n) { if (sonPoint + 1 < n && a[sonPoint + 1] < a[sonPoint]) //存在右子结点的话,在左右孩子中找较小数 sonPoint++; if (a[sonPoint] >= temp)//再和父结点对比,如果父结点比较大不用做交换 break; else {//否则把较小的子结点往上移动,替换它的父结点 a[fatherPoint] = a[sonPoint]; fatherPoint = sonPoint; sonPoint = 2 * fatherPoint + 1; } } a[fatherPoint] = temp; } /// <summary> /// 在最小堆中删除数(删除根节点) /// </summary> /// <param name="a"></param> /// <param name="n">结点个数</param> public static void MinHeapDeleteNumber(int[] a, int n) { Swap(a, 0, n - 1); //互换根节点和叶子结点后 MinHeapFixDown(a, 0, n - 1);//向下调整 } /// <summary> /// 建立最小堆 n为结点总数 /// </summary> /// <param name="a">数组</param> /// <param name="n">结点总数</param> public static void MakeMinHeap(int[] a, int n) { for (int i = (n-1-1)/ 2 ; i >= 0; i--)//由最后一个结点的父结点开始向下调整 MinHeapFixDown(a, i, n); }
算法案例