查找""排序""简单数学计算" "简单算法"[Java实现](数据结构和算法)(复习)(持续更新

排序法

最差时间分析 平均时间复杂度 稳定度 空间复杂度
冒泡排序 O(n2) O(n2) 稳定 O(1)
快速排序 O(n2) O(n*log2n) 不稳定 O(log2n)~O(n)
选择排序 O(n2) O(n2) 不稳定 O(1)
二叉树排序 O(n2) O(n*log2n) 稳定 O(n)

插入排序

O(n2) O(n2) 稳定 O(1)
堆排序 O(n*log2n) O(n*log2n) 不稳定 O(1)
希尔排序 O O 不稳定 O(1)



折半查找(非递归)

/**
	 * 折半查找算法(非递归形式)
	 * 
	 * @param array
	 * @param key
	 * @return
	 */
	public static int Bsearch(int array[], int key) {
		int mid;
		int low = 0;
		int high = array.length - 1;
		while (low <= high) {
			mid = (low + high) / 2;
			if (key == array[mid])
				return mid;
			else if (key < array[mid])
				high = mid - 1;
			else
				low = mid + 1;
		}
		return -1;
	}

折半查找(递归)

/**
	 * 折半查找算法(递归形式)
	 * @param array
	 * @param low
	 * @param high
	 * @param key
	 * @return
	 */
	public static int BsearchRec(int array[], int low, int high, int key) {
		int mid;
		if (low <= high) {
			mid = (low + high) / 2;
			if (key == array[mid])
				return mid;
			else if (key < array[mid])
				return BsearchRec(array, low, mid - 1, key);
			else
				return BsearchRec(array, mid + 1, high, key);
		}
		return -1;
	}

直接插入排序

一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:(wiki)

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置中
  6. 重复步骤2~5

/**
	 * 直接插入排序
	 * 
	 * @param array
	 * @return
	 */
	public static int[] InsertSort(int array[]) {
		int n = array.length;
		int i, j;
		for (i = 0; i < n; i++) {// 对所有的元素都进行插入操作:n个元素
			int temp = array[i];
			for (j = i; j > 0 && temp < array[j - 1]; j--) {
				// 将该元素和它前面所有的元素比较,并将小于它的元素往后移
				array[j] = array[j - 1];
			}
			array[j] = temp;// 将最后一个小于它的元素覆盖
		}
		return array;
	}
public void insertSort(int a[]) {
		int n = a.length;
		int temp;
		int j;
		for (int i = 1; i < n; i++) {
			temp = a[i];
			for (j = i - 1; j >= 0 && temp < a[j]; j--) {
				a[j + 1] = a[j];
			}
			a[j + 1] = temp;
		}
		for (int i = 0; i < a.length; i++) {
			System.out.print(a[i] + " ");
		}
	}


冒泡排序

重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

冒泡排序算法的运作如下:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

/**
	 * 冒泡排序
	 * 
	 * @param array
	 * @return
	 */
	public static int[] BubbleSort(int array[]) {
		boolean flag = true;
		int n = array.length;
		int temp = 0;
		for (int i = 0; i < n - 1; i++) {// 冒泡排序的轮数:n-1次,每一轮都将该轮中最大的元素放在末尾
			flag = true;
			for (int j = 0; j < n - i - 1; j++) {// 具体的一轮:j与j+1进行比较和交换,j的最大值是n-i-1
				if (array[j] > array[j + 1]) {
					temp = array[j];
					array[j] = array[j + 1];
					array[j + 1] = temp;
					flag = false;
				}// 如果前面的元素都是有序,则该轮for循环结束后flag都是true,直接退出
			}
			if (flag == true)
				break;
		}
		return array;
	}

冒泡算法2,从小到大排序, 从左到右,更符合冒泡思想,小的数字向上

/**
	 * 冒泡算法2,从小到大排序, 从左到右,更符合冒泡思想,小的数字向上排
	 * 
	 * @param array
	 * @return
	 */
	public static int[] BubbleSort2(int array[]) {
		boolean flag = true;// 标志位,当满足顺序时,如果i仍然没有遍历到倒数第二个元素则可以直接退出。
		int n = array.length;
		int temp = 0;
		for (int i = 0; i < n - 1; i++) {// n-1轮(最后一轮只剩下一个不用排)
			flag = true;
			for (int j = n - 1; j > i; j--) {// 将最小的一个数放在通过冒泡,放置到第i个位置
				if (array[j] < array[j - 1]) {
					temp = array[j - 1];
					array[j - 1] = array[j];
					array[j] = temp;
					flag = false;
				}
			}
			if (flag == true)
				break;
			for (int k = 0; k < array.length; k++) {
				System.out.print(array[k] + " ");
			}
			System.out.println("");
		}
		return array;
	}


简单选择排序

它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾。以此类推,直到所有元素均排序完毕。

/**
	 * 简单选择排序
	 * 
	 * @param array
	 * @return
	 */
	public static int[] SelectSort(int array[]) {
		int n = array.length;
		int i, j, min, temp;
		for (i = 0; i < n - 1; i++) {// n-1次最小数的选择,因为最后一个肯定是最后一轮中最小的的,所以不用比较
			min = i;
			for (j = i + 1; j < n; j++)
				// 从当前元素后面的元素中选择一个最小的和当前元素交换
				if (array[j] < array[min])
					min = j;
			temp = array[i];
			array[i] = array[min];
			array[min] = temp;
		}
		return array;
	}
 
 
 
 
 
 
 
 


快速排序

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。

步骤为:

  1. 从数列中挑出一个元素,称为 "基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割结束之后,该基准就处于数列的中间位置。这个称为分割(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递回的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递回下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。


/**
	 * 快速排序算法
	 * 
	 * 一趟快速排序的过程 1)设置两个变量I、J,排序开始的时候:I=0,J=N-1;
	 * 2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
	 * 3)从J开始向前搜索,即由后开始向前搜索(J=J-1),找到第一个小于key的值A[J],停下来进入4;
	 * 4)从I开始向后搜索,即由前开始向后搜索(I=I+1),找到第一个大于key的A[I],将A[I]与A[J]交换; 5)重复第3、4步,直到
	 * I=J; (3,4步是在程序中没找到时候j=j-1,i=i+1,直至找到为止。 找到并交换的时候i,
	 * j指针位置不变。另外当i=j这过程一定正好是i+或j-完成的最后另循环结束。)
	 * 
	 * @param array
	 * @param low
	 * @param high
	 */
	public void QuickSort(int array[], int low, int high) {
		int pivotkey, i, j;
		if (low < high) {
			pivotkey = array[low];
			i = low;
			j = high;
			while (i < j) {
				while (i < j && array[j] >= pivotkey)
					j--;
				if (i < j)
					array[i++] = array[j];
				while (i < j && array[i] <= pivotkey)
					i++;
				if (i < j)
					array[j--] = array[i];
			}
			array[i] = pivotkey;
			QuickSort(array, low, i - 1);
			QuickSort(array, i + 1, high);
		}
	}


归并排序

/**
	 * 归并排序:对两个已经有序的数组进行排序的算法
	 * 
	 * @param arrayA
	 * @param arrayB
	 * @return
	 */
	public static int[] MergeSort(int[] arrayA, int[] arrayB) {
		int[] arrayC = new int[arrayA.length + arrayB.length];
		int k = 0;
		int i = 0;
		int j = 0;
		while (i < arrayA.length && j < arrayB.length) {
			if (arrayA[i] < arrayB[j])
				arrayC[k++] = arrayA[i++];
			else
				arrayC[k++] = arrayB[j++];
		}
		while (i < arrayA.length)
			arrayC[k++] = arrayA[i++];
		while (j < arrayB.length)
			arrayC[k++] = arrayB[j++];
		return arrayC;
	}

希尔排序

算法基本思想:

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组,所有距离为d1倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后第二个增量d2<d1重复上诉的分组和排序,直到取值为 dt = 1,即所有记录放在同一个组中进行直接插入排序。

public void shellSort(int a[]) {
		int n = a.length;
		int d = n / 2;
		int temp;
		int i;
		int j;
		int k;
		while (d != 0) {
			for (i = 0; i < d; i++) {
				for (j = i + d; j < n; j = j + d) {
					temp = a[j];
					for (k = j - d; k >= 0 && temp < a[k]; k = k - d) {
						a[k + d] = a[k];
					}
					a[k + d] = temp;
				}
			}
			d = d / 2;
		}
	}



public class ShellSort {
	public static int[] a = { 10, 32, 1, 9, 5, 7, 12, 0, 4, 3 };

	public static void main(String args[]) {
		int i; // 循环计数变量
		int Index = a.length;// 数据索引变量
		System.out.print("排序前: ");
		for (i = 0; i < Index - 1; i++)
			System.out.printf("%3s ", a[i]);
		System.out.println("");
		shellSort(Index - 1); // 选择排序
		// 排序后结果
		System.out.print("排序后: ");
		for (i = 0; i < Index - 1; i++)
			System.out.printf("%3s ", a[i]);
		System.out.println("");
	}

	public static void shellSort(int Index) {
		int j, k; // 循环计数变量
		int Temp; // 暂存变量
		boolean Change; // 数据是否改变
		int DataLength; // 分割集合的间隔长度
		int Pointer; // 进行处理的位置
		DataLength = (int) Index / 2; // 初始集合间隔长度
		while (DataLength != 0) // 数列仍可进行分割
		{
			// 对各个集合进行处理
			for (j = DataLength; j < Index; j++) {
				Change = false;
				Temp = a[j]; // 暂存Data[j]的值,待交换值时用
				Pointer = j - DataLength; // 计算进行处理的位置
				// 进行集合内数值的比较与交换值
				while (Temp < a[Pointer] && Pointer >= 0 && Pointer <= Index) {
					a[Pointer + DataLength] = a[Pointer];
					// 计算下一个欲进行处理的位置
					Pointer = Pointer - DataLength;
					Change = true;
					if (Pointer < 0 || Pointer > Index)
						break;
				}
				// 与最后的数值交换
				a[Pointer + DataLength] = Temp;
				if (Change) {
					// 打印目前排序结果
					System.out.print("排序中: ");
					for (k = 0; k < Index; k++)
						System.out.printf("%3s ", a[k]);
					System.out.println("");
				}
			}
			DataLength = DataLength / 2; // 计算下次分割的间隔长度
		}
	}
}


最大公约数,辗转相除法

public static int gcd(int x, int y) {
		if (y == 0)
			return x;
		else
			return gcd(y, x % y);
	}

最大公约数

/**
	 * 最大公约数函数
	 * 
	 * @param num1
	 * @param num2
	 * @return
	 */
	public static int gcd(int num1, int num2) {
		int r = 0;
		while (num2 != 0) {
			r = num1 % num2;
			num1 = num2;
			num2 = r;
		}
		return num1;
	}

减法~

// 传入的x大于y
	public static int gcd(int x, int y) {
		if (x < y)
			return gcd(y, x);
		if (y == 0)
			return x;
		else
			return gcd(x - y, y);
	}



寻找数组中重复次数的最多的那个数(数组有上限)

/**
	 * 
	 * @param array
	 *            待寻找重复数的数组
	 * @param num
	 *            预设不同数的个数(有上限的情况下)
	 */
	public static int FindRepeatest(int array[], int num) {
		// 存放每个数的重复次数(重复度)
		int[] assistArray = new int[num];
		// 当前个数最多的那个数
		int max = 0;
		for (int i = 0; i < array.length; i++) {
			assistArray[array[i]]++;
			if (assistArray[array[i]] > assistArray[max])
				max = array[i];
		}
		return max;
	}

斐波那契序列

public class Fibonacci {
	public int F(int n) {
		if (n <= 0)
			return 0;
		else if (n == 1)
			return 1;
		else
			return F(n - 1) + F(n - 2);
	}
}

public class Fibonacci2 {
	public int F2(int a, int b, int n) {
		if (n == 1)
			return a;
		else if (n == 2)
			return b;
		else
			return F2(a, b, n - 1) + F2(a, b, n - 2);
	}
}

汉诺塔问题:

public class Hanoi {
	private int c = 0;

	public void hanoi(int n, char x, char y, char z) {
		if (n == 1) {
			move(x, 1, z);
		} else {
			hanoi(n - 1, x, z, y);
			move(x, n, z);
			hanoi(n - 1, y, x, z);
		}
	}

	public void move(char x, int n, char z) {

		System.out.println(++c + ".移动" + n + "从" + x + "到" + z);
	}

	public static void main(String[] args) {
		Hanoi hanoi = new Hanoi();
		hanoi.hanoi(3, 'x', 'y', 'z');
	}
}















你可能感兴趣的:(java,数据结构,工作,算法,PIVOT,数学计算)