算法
六大排序算法
package com.GWL.test;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
* 排序算法:
* 简单排序:冒泡排序、选择排序、插入排序
* 高级排序:希尔排序、归并排序、快速排序
* */
public class TestComparable {
public static void main(String[] args) {
kuaiSuD();
}
// 冒泡排序算法
public static void maoPao() {
//将最大数放最后面
int[] ints = {5, 4, 8, 1, 4, 8, 7, 9};
int s;
for (int i = ints.length - 1; i > 0; i--) {
for (int j = 0; j < i; j++) {
if (ints[j] > ints[i]) {
s = ints[j];
ints[j] = ints[i];
ints[i] = s;
}
}
}
System.out.println(Arrays.toString(ints) + "冒泡排序:时间复杂度:O(n^2)");
}
// 选择排序算法
public static void xuanZhe() {
int[] arr = {0, 4, 8, 1, 3, 2, 11, 9};
// 用于记录最小值的下标
int min = 0;
int x;
for (int i = 0; i < arr.length - 1; i++) {
min = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[min] > arr[j]) {
min = j;
}
}
// 最小值放在左边
x = arr[i];
arr[i] = arr[min];
arr[min] = x;
}
System.out.println(Arrays.toString(arr) + "选择排序:时间复杂度:O(n^2)");
}
// 插入排序算法
public static void chaRu() {
int[] arr = {3, 4, 1, 8, 1, 9, 5, 11, 2, 6};
int x;
for (int i = 1; i < arr.length; i++) {
// 老师的
for (int j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
x = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = x;
} else {
break;
}
}
// 我的
// for (int j = i - 1; j >= 0; j--) {
// if (arr[i] < arr[j]) {
// x = arr[i];
// arr[i] = arr[j];
// arr[j] = x;
// i=j;
// }else {
// break;
// }
// }
}
System.out.println(Arrays.toString(arr) + "插入排序时间复杂度:O(N^2)");
}
// 希尔排序,插入排序的优化,分组插入
public static void xiEr() {
int[] arr = {3, 4, 1, 8, 1, 9, 5, 11, 2, 6};
// 1、 根据数组的长度确认分组大小
int h = 1;
while (h < arr.length / 2) {
h = 2 * h + 1;
}
// 2、 排序
while (h >= 1) {
int x;
for (int i = h; i < arr.length; i++) {
for (int j = i; j >= h; j -= h) {
if (arr[j] < arr[j - h]) {
x = arr[j - h];
arr[j - h] = arr[j];
arr[j] = x;
} else {
break;
}
}
}
System.out.println(Arrays.toString(arr));
h = (int) h / 2;
}
}
// 归并排序算法调用
public static void guiBing() {
int[] arr = {3, 4, 1, 8, 9, 5, 11, 2, 6, 3, 21, 4, 5};
int[] str = new int[arr.length];
guiBin(arr, 0, arr.length - 1, str);
System.out.println(Arrays.toString(str) + "归并算法时间复杂度:O(nlogn)");
}
// 归并算法主体
public static void guiBin(int[] arr, int x, int y, int[] str) {
// 数据数组arr,辅助数组str;
int z;
if (x >= y) {
// 递归出口,当分组成员个数为一时,结束递归
return;
} else {
// 当分组成员个数大于二都要分组
z = (x + y) / 2;
guiBin(arr, x, z, str);
guiBin(arr, z + 1, y, str);
// 先定义三个指针,分别指向需要合并的两个分组的头元素,以及辅助数组的起始对应位置
int a = x;
int b = z + 1;
int i = x;
// 当每一组的指针没溢出时,依次比较两组的元素大小,并将小的存入辅助数组
while (a <= z && b <= y) {
if (arr[a] > arr[b]) {
str[i++] = arr[b++];
} else {
str[i++] = arr[a++];
}
}
// 其中一组先结束则遍历另一组直接顺序存入
while (a <= z) {
str[i++] = arr[a++];
}
while (b <= y) {
str[i++] = arr[b++];
}
// 此时辅助数组中的元素已经排序完成,现在将数据辅助回原始数组
for (int j = x; j <= y; j++) {
arr[j] = str[j];
}
}
}
// 快速排序算法调用
public static void kuaiSuD(){
int[] arr = {3, 4, 1, 8, 9, 5, 11, 2, 6, 3, 21, 4, 5};
kuaiSu(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr) + "快速算法时间复杂度:O(nlogn)");
}
// 快速排序算法
public static void kuaiSu(int[] arr, int x, int y) {
// 递归出口,分组至但个元素结束结束
if (x >= y) {
return;
} else {
// 记住第一份元素的值,作为分界点,两头指针依次内移
int s = arr[x];
int a = x;
int b = y + 1;
while (true) {
// 右边指针遇到小于分界点元素是停止移动
while (arr[--b] > s) {
if (a >= b) {
break;
}
}
// 左边指针遇到大于分界点的元素时停止右移
while (arr[++a] < s) {
if (a >= b) {
break;
}
}
// 若两指针相遇着结束移动 ,否则交换两指针的数值
if (a >= b) {
break;
} else {
int i = arr[b];
arr[b] = arr[a];
arr[a] = i;
}
}
// 因为有指针停留处,元素一定小于分界点,交换右指针与分界点的数值
int e = arr[b];
arr[b] = s;
arr[x] = e;
// 分界点两边再次分组
kuaiSu(arr, x, b - 1);
kuaiSu(arr, b + 1, y);
}
}
}
链表实现LinkList()
package com.GWL.suanFa;
import org.w3c.dom.Node;
import java.util.Iterator;
//继承Iterable<T>可用于遍历链表
public class LinkList<T> implements Iterable<T> {
// 头结点
public Node head;
// 链表长度
private int N;
//节点
private class Node {
// 节点数值
T item;
// 下一节点
Node next;
public Node(T item, Node next) {
this.item = item;
this.next = next;
}
}
public LinkList() {
this.head = new Node(null, null);
this.N = 0;
}
//链表长度
public int length() {
return this.N;
}
//添加链表元素
public void add(T item) {
Node pre = head;
for (int i = 0; pre.next != null; i++) {
pre = pre.next;
}
pre.next = new Node(item, null);
this.N++;
}
//通过索引查找对应元素
public T selectOne(int n) {
Node pre = head;
for (int i = 0; i < n; i++) {
pre = pre.next;
}
T t = pre.next.item;
return t;
}
// 通过索引删除对应元素
public T deleteOne(int n) {
Node pre = head;
for (int i = 0; i < n; i++) {
pre = pre.next;
}
Node s = pre.next;
pre.next = s.next;
N--;
return s.item;
}
//在指定位置插入新内容
public void insertOne(int n, T s) {
Node pre = head;
for (int i = 0; i < n; i++) {
pre = pre.next;
}
Node ing = new Node(s, pre.next);
pre.next = ing;
N++;
}
// 继承Iterable<T>,并重写方法,再继承Iterator<T>重写两个方法,就可以for循环遍历了
@Override
public Iterator<T> iterator() {
return new ing();
}
private class ing implements Iterator {
private LinkList.Node n;
public ing() {
this.n = head;
}
@Override
public boolean hasNext() {
return n.next != null;
}
@Override
public Object next() {
n = n.next;
return n.item;
}
}
// 链表反转
public void resti() {
if (N == 0) {
return;
} else {
rest(head.next);
}
}
//节点反转递归部分
public Node rest(Node n) {
// 出口,原尾结点成为新头结点
if (n.next == null) {
head.next = n;
return n;
} else {
// 当前节点转为原上一节点的next节点
rest(n.next).next = n;
// 原头结点转为尾结点
n.next = null;
return n;
}
}
}
链表实现HashMap<key,value>()
package com.GWL.suanFa;
import org.w3c.dom.Node;
public class HashMap<key, value> {
public Node head;
public int N;
public class Node {
public key key;
public value value;
public Node next;
public Node(key key, value value, Node next) {
this.key = key;
this.value = value;
this.next = next;
}
}
public HashMap() {
this.head = new Node(null, null, null);
this.N = 0;
}
public void put(key key, value value) {
Node n = head;
while (n.next != null) {
n = n.next;
if (key.equals(n.key)) {
n.value = value;
return;
}
}
// 这里头处加
head.next = new Node(key, value, head.next);
N++;
}
public int size() {
return N;
}
public value getValue(key key) {
Node n = head;
while (n.next != null) {
n = n.next;
if (key.equals(n.key)) {
return n.value;
}
}
return null;x`
}
}
链表实现树tree
package com.GWL.suanFa;
import org.w3c.dom.Node;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree<key extends Comparable<key>, value> {
private Node root;
private int N;
// 创建节点内部类
private class Node {
public key key;
public value value;
public Node left;
public Node right;
public Node(key key, value value, Node left, Node right) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
}
}
public BinaryTree() {
this.root = null;
this.N = 0;
}
public int length() {
return N;
}
//添加数据
public void put(key key, value value) {
this.root = put(root, key, value);
}
private Node put(Node x, key key, value value) {
if (x == null) {
N++;
return new Node(key, value, null, null);
} else {
int a = key.compareTo(x.key);
if (a > 0) {
x.right = put(x.right, key, value);
} else if (a < 0) {
x.left = put(x.left, key, value);
} else {
x.value = value;
}
return x;
}
}
// 通过key获取值
public value getValue(key key) {
return getValue(root, key);
}
private value getValue(Node x, key key) {
if (x == null) {
return null;
}
int a = key.compareTo(x.key);
if (a == 0) {
return x.value;
} else if (a < 0) {
return getValue(x.left, key);
} else {
return getValue(x.right, key);
}
}
// 通过key删除节点;将
public void deleteByKey(key key) {
deleteByKey(root, key);
}
private Node deleteByKey(Node x, key key) {
if (x == null) {
return null;
}
int a = key.compareTo(x.key);
if (a > 0) {
x.right = deleteByKey(x.right, key);
return x;
} else if (a < 0) {
x.left = deleteByKey(x.left, key);
return x;
} else {
{
// 此时X为需要删除的那个节点
// 若其左节点为空,直接返回右节点
if (x.left == null) {
N--;
return x.right;
}
// 若其右节点为空,直接返回左节点
if (x.right == null) {
N--;
return x.left;
}
// 若左右节点都不为空,找到右子树中最小值,即右子树中最左的节点,替换被删除的节点的位置
Node n = x.right;
Node y = null;
if (n.left == null) {
n.left = x.left;
} else {
// 找到最后一个左节点为空的节点,将其右节点赋值为其父节点的左节点
while (n.left != null) {
y = n;
n = n.left;
}
y.left = n.right;
//替换被删除的节点的位置
n.left = x.left;
n.right = x.right;
}
N--;
return n;
}
}
}
// 树的最大深度
public int zuiShen() {
return zuiShen(root);
}
private int zuiShen(Node n) {
if (n == null) {
return 0;
}
int x = zuiShen(n.left);
int y = zuiShen(n.right);
return x > y ? x + 1 : y + 1;
}
// 中序遍历、前序遍历、后序遍历
public Collection<String> zhong() {
//此为队列,可用链表实现,先进先出
//通过控制每个节点的值存入队列的顺序,控制值出队列的顺序,实现前、中、后遍历
Queue<String> strings = new LinkedList<>();
zhong(root, strings);
return strings;
}
private void zhong(Node n, Queue<String> strings) {
if (n == null) {
return;
}
if (n.left != null) {
zhong(n.left, strings);
}
// 数据存入列队,这一行放中间就是中序遍历
strings.add(String.valueOf(n.key));
if (n.right != null) {
zhong(n.right, strings);
}
}
}
链表实现红黑树
每个节点都有一个键值对存储该节点与其父节点的链接颜色,1、根节点总为黑色,2、红色链接在左边,3、红色链接不能连续的红色,而刚添加的一个节点其与父节点的链接为红色,如果时添加右子树,为了防止红色在右边,需要左旋,
package com.GWL.suanFa;
import org.w3c.dom.Node;
public class RedBlackTree<key extends Comparable<key>, value> {
private Node root;
private int N;
private static final boolean RED = true;
private static final boolean BLACK = false;
private class Node {
public key key;
public value value;
public Node left;
public Node right;
public boolean color;
public Node(key key, value value, Node left, Node right, boolean color) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
this.color = color;
}
}
public int length() {
return N;
}
private boolean isRed(Node n) {
if (n == null) {
return false;
}
return n.color == RED;
}
// 左旋
private Node leftZhuan(Node x) {
Node y = x.right;
x.right = y.left;
y.left = x;
y.color = x.color;
x.color = BLACK;
return y;
}
// 右旋
private Node rightZhuan(Node x) {
Node y = x.left;
x.left = y.right;
y.right = x;
y.color = x.color;
x.color = RED;
return y;
}
// 颜色反转
private void colorZhuan(Node x) {
x.right.color = BLACK;
x.left.color = BLACK;
x.color = RED;
}
public void put(key key, value value) {
root = put(root, key, value);
root.color = BLACK;
}
private Node put(Node x, key key, value value) {
if (x == null) {
N++;
return new Node(key, value, null, null, RED);
}
int a = key.compareTo(x.key);
if (a > 0) {
x.right = put(x.right, key, value);
} else if (a < 0) {
x.left = put(x.left, key, value);
} else {
x.value = value;
}
// 进行左旋:当前节点的左节点为黑色,右节点为红色
if (isRed(x.right) && !isRed(x.left)) {
x = leftZhuan(x);
}
// 进行右旋:当前左节点和左节点的左节点都为红色
if (isRed(x.left) && isRed(x.left.left)) {
x = rightZhuan(x);
}
// 颜色反转:当前节点的左右节点都为红色
if (isRed(x.right) && isRed(x.left)) {
colorZhuan(x);
}
return x;
}
// 通过key获取值
public value getValue(key key) {
return getValue(root, key);
}
private value getValue(Node x, key key) {
if (x == null) {
return null;
}
int a = key.compareTo(x.key);
if (a > 0) {
return getValue(x.right, key);
} else if (a < 0) {
return getValue(x.left, key);
} else {
return x.value;
}
}
}