首页 > 代码库 > 常用算法
常用算法
快速排序
维基百科详细说明
public static void QuickSort(int[] numbers, int left, int right) { if (left < right) { int middle = numbers[(left + right) / 2]; int i = left - 1; int j = right + 1; while (true) { while (numbers[++i] < middle) { } while (numbers[--j] > middle) { } if (i >= j) break; Swap(numbers, i, j); } QuickSort(numbers, left, i - 1); QuickSort(numbers, j + 1, right); } } public static void Swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }
冒泡排序
public static void BubbleSort(int[] arr) { int n = arr.Length; for (int i = 0; i < n - 1; i++) { for (int j = i + 1; j < n; j++) { if (arr[i] > arr[j]) { int temp; temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } }
选择排序
public static void SelectionSort(int[] arr) { int smallIndex; int pass; int j; int temp; int n = arr.Length; for (pass = 0; pass < n - 1; pass++) { // 假定最小值初始时是arr[pass]=1st smallIndex = pass; // 遍历子列表,从arr[pass+1]到arr[n-1] //j从pass+1开始,因为从0到pass已经是有序的了 for (j = pass + 1; j < n; j++) { //如果发现小元素,把当前元素的索引赋值给最小值 //这其实就是一个找最小元素的过程 if (arr[j] < arr[smallIndex]) { smallIndex = j; } } //交换 temp = arr[pass]; arr[pass] = arr[smallIndex]; arr[smallIndex] = temp; } }
插入排序
public static void InsertSort(int[] arr) { int i, j; int n = arr.Length; int target; //假定第一个元素被放到了正确的位置上 //这样,仅需遍历1 - n-1 for (i = 1; i < n; i++) { j = i; target = arr[i]; while (j > 0 && target < arr[j - 1]) { arr[j] = arr[j - 1]; j--; } arr[j] = target; } }
二分查找
递归写法:
public static int BinarySearch(int[] arr, int low, int high, int key) { int mid = low + (high - low) / 2; if (low > high) return -1; else { if (arr[mid] == key) return mid; else if (arr[mid] > key) return BinarySearch(arr, low, mid - 1, key); else return BinarySearch(arr, mid + 1, high, key); } }
循环写法:
public static int BinarySearch(int[] data, int low, int high, int x) { int mid;//中间位置 if (low > high) { return -1; } while (low <= high) { mid = (low + high) / 2; if (x == data[mid]) { return mid; } else if (data[mid] < x) { low = mid + 1; } else if (data[mid] > x) { high = mid - 1; } } return -1; }
求质数算法
定理: 如果n不是素数, 则n有满足1<d<=sqrt(n)的一个因子d.
证明: 如果n不是素数, 则由定义n有一个因子d满足1<d<n.
如果d大于sqrt(n), 则n/d是满足1<n/d<=sqrt(n)的一个因子.
尝试从2到\sqrt{N}的整数是否整除N。
素数定义(维基百科)
/*埃拉托斯特尼篩法*/ public static bool IsPrime(int x) { int i; if (x <= 1)/*1不是質數,且不考慮負整數與0,故輸入x<=1時輸出為假*/ { return false; } for (i = 2; i * i <= x; ++i) { if (x % i == 0)/*若整除時輸出為假,否則輸出為真*/ { return false; } } return true; }
求最大公约数算法
最大公约数(维基百科)
1、查找约数法.
先分别找出每个数的所有约数,再从两个数的约数中找出公有的约数,其中最大的一个就是最大公约数.
例如,求12和30的最大公约数. 12的约数有:1、2、3、4、6、12;
30的约数有:1、2、3、5、6、10、15、30.
12和30的公约数有:1、2、3、6,其中6就是12和30的最大公约数.
2 、更相减损术
《九章算术》是中国古代的数学专著,其中的“更相减损术”可以用来求两个数的最大公约数,即“可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。” 翻译成现代语言如下:
第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。 则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。
其中所说的“等数”,就是最大公约数。求“等数”的办法是“更相减损”法。
如下:
91 49
42 49
42 7
35 7
28 7
21 7
14 7
7 7
这里得到的7就叫做“等数”,91和49都是这等数的重叠(即倍数),故7为其公约数.而7和7的最大公约数就是7,(7,7)=7,所以(91,49)=(42,7)=(7,7)=7
//更相减损法 public static int Gcd(int a, int b) { while (a != b) { if (a > b) a -= b; else b -= a; } return a; }
3、辗转相除法.
又名欧几里德算法(Euclidean algorithm)乃求两个正整数之最大公因子的算法
当两个数都较大时,采用辗转相除法比较方便.其方法是:
以小数除大数,如果能整除,那么小数就是所求的最大公约数.否则就用余数来除刚才的除数;再用这新除法的余数去除刚才的余数.依此类推,直到一个除法能够整除,这时作为除数的数就是所求的最大公约数.
例如:求4453和5767的最大公约数时,可作如下除法.
5767÷4453=1余1314
4453÷1314=3余511
1314÷511=2余292
511÷292=1余219
292÷219=1余73
//辗转相除法--递归 public static int Gcd(int a, int b) { if (b == 0) return a; else return Gcd(b, a % b); } //辗转相除法--纯循环 public static int GcdIterate(int a, int b) { int r; while (b != 0) { r = a % b; a = b; b = r; } return a; }
最小公倍数
最小公倍数(维基百科)
public static float minGongBeiShu(int n1, int n2) { int temp = Math.Max(n1, n2); n2 = Math.Min(n1, n2);//n2中存放两个数中最小的 n1 = temp;//n1中存放两个数中最大的 int product = n1 * n2;//求两个数的乘积 while (n2 != 0) { n1 = n1 > n2 ? n1 : n2;//使n1中的数大于n2中的数 int m = n1 % n2; n1 = n2; n2 = m; } return (product / n1);//最小公倍数 }