();
199 | list.add(3);
200 | list.add(1);
201 | list.add(9);
202 | list.add(5);
203 | Collections.sort(list);
204 |
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/binarytree/BinaryTreeTraversal.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.binarytree;
2 |
3 | /**
4 | * 二叉树的先序遍历,中序遍历,后序遍历的递归实现
5 | * 对于左,根,右
6 | * 先序遍历: 根最先, 根->左->右
7 | * 中序遍历: 跟在中间, 左->根 -> 右
8 | * 后序遍历: 根在最后, 左->右->根
9 | */
10 | public class BinaryTreeTraversal {
11 | /**
12 | * @author yaobo
13 | * 二叉树的先序中序后序排序
14 | */
15 | public Node init() {//注意必须逆序建立,先建立子节点,再逆序往上建立,因为非叶子结点会使用到下面的节点,而初始化是按顺序初始化的,不逆序建立会报错
16 | Node J = new Node(8, null, null);
17 | Node H = new Node(4, null, null);
18 | Node G = new Node(2, null, null);
19 | Node F = new Node(7, null, J);
20 | Node E = new Node(5, H, null);
21 | Node D = new Node(1, null, G);
22 | Node C = new Node(9, F, null);
23 | Node B = new Node(3, D, E);
24 | Node A = new Node(6, B, C);
25 | return A; //返回根节点
26 | }
27 |
28 | public void printNode(Node node) {
29 | System.out.print(node.getData());
30 | }
31 |
32 | public void thePreTraversal(Node root) { //先序遍历
33 | printNode(root);
34 | if (root.getLeftNode() != null) { //使用递归进行遍历左孩子
35 | thePreTraversal(root.getLeftNode());
36 | }
37 | if (root.getRightNode() != null) { //递归遍历右孩子
38 | thePreTraversal(root.getRightNode());
39 | }
40 | }
41 |
42 | public void theMidOrderTraversal(Node root) { //中序遍历
43 | if (root.getLeftNode() != null) {
44 | theMidOrderTraversal(root.getLeftNode());
45 | }
46 | printNode(root);
47 | if (root.getRightNode() != null) {
48 | theMidOrderTraversal(root.getRightNode());
49 | }
50 | }
51 |
52 |
53 | public void thePostOrderTraversal(Node root) { //后序遍历
54 | if (root.getLeftNode() != null) {
55 | thePostOrderTraversal(root.getLeftNode());
56 | }
57 | if (root.getRightNode() != null) {
58 | thePostOrderTraversal(root.getRightNode());
59 | }
60 | printNode(root);
61 | }
62 |
63 | public static void main(String[] args) {
64 | BinaryTreeTraversal tree = new BinaryTreeTraversal();
65 | Node root = tree.init();
66 | System.out.println("先序遍历");
67 | tree.thePreTraversal(root);
68 | System.out.println("");
69 | System.out.println("中序遍历");
70 | tree.theMidOrderTraversal(root);
71 | System.out.println("");
72 | System.out.println("后序遍历");
73 | tree.thePostOrderTraversal(root);
74 | System.out.println("");
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/binarytree/Node.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.binarytree;
2 |
3 | /**
4 | * Referenced by
5 | */
6 | public class Node {
7 | private int data;
8 | private Node leftNode;
9 | private Node rightNode;
10 |
11 | public Node(int data, Node leftNode, Node rightNode) {
12 | this.data = data;
13 | this.leftNode = leftNode;
14 | this.rightNode = rightNode;
15 | }
16 |
17 | public int getData() {
18 | return data;
19 | }
20 |
21 | public void setData(int data) {
22 | this.data = data;
23 | }
24 |
25 | public Node getLeftNode() {
26 | return leftNode;
27 | }
28 |
29 | public void setLeftNode(Node leftNode) {
30 | this.leftNode = leftNode;
31 | }
32 |
33 | public Node getRightNode() {
34 | return rightNode;
35 | }
36 |
37 | public void setRightNode(Node rightNode) {
38 | this.rightNode = rightNode;
39 | }
40 | }
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/datastructure/LinearTable/FibonacciSequence.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.datastructure.LinearTable;
2 |
3 | /**
4 | * https://www.jb51.net/article/45596.htm
5 | * 算法复杂度分析,参考网页文章
6 | * https://blog.csdn.net/a1456123a/article/details/48849923
7 | * https://bbs.pediy.com/thread-123051.htm
8 | */
9 | public class FibonacciSequence {
10 | public static void main(String[] args) {
11 | // 0, 1, 1, 2, 3, 5, 8
12 | int result = f(6);
13 | System.out.println("f(6)=" + result);
14 | }
15 |
16 | private static int f(int n) {
17 | int result = -1;
18 | int temp1 = 0;
19 | int temp2 = 1;
20 | for (int index = 0; index <= n; index++) {
21 | if (index == 0) {
22 | result = temp1;
23 | } else if (index == 1) {
24 | result = temp2;
25 | } else {
26 | result = temp1 + temp2;
27 | if (result < 0) {
28 | result = -2;
29 | break;
30 | }
31 | temp1 = temp2;
32 | temp2 = result;
33 | }
34 | }
35 |
36 | return result;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/datastructure/MyHashMap.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.datastructure;
2 |
3 | import java.util.HashMap;
4 |
5 | /**
6 | * 基于HashTable 哈希表简历的HashMap
7 | * Hash 拉链法解决哈希冲突
8 | * 源码参考了文章https://blog.csdn.net/null_xv/article/details/79753450
9 | *
10 | * 名词解释: 冲突解决技术可以分为两类:开散列方法( open hashing,也称为拉链法,separate chaining )
11 | * 和闭散列方法( closed hashing,也称为开地址方法,open addressing )。
12 | * 这两种方法的不同之处在于:开散列法把发生冲突的关键码存储在散列表主表之外,而闭散列法把发生冲突的关键码存储在表中另一个槽内。
13 | * 这里的源码,是采用了拉链法Separate Chaining method
14 | */
15 | public class MyHashMap {
16 | public static void main(String[] args) {
17 | MyHashMap map = new MyHashMap();
18 | String key = "test-key";
19 | map.put(key, "vvv1");
20 | String value = (String) map.get(key);
21 | System.out.println("map.get()=" + value);
22 | }
23 |
24 | Node[] nodes;
25 | int intsize;
26 |
27 | private MyHashMap(int intsize) {
28 | this.intsize = intsize;
29 | nodes = new Node[intsize];
30 | }
31 |
32 | /**
33 | * 初始化大小,需要优化
34 | */
35 | public MyHashMap() {
36 | this(1024 * 1024);
37 | }
38 |
39 | public boolean isEmpty() {
40 | return intsize == 0;
41 | }
42 |
43 | public void put(Object key, Object value) {
44 | int h = hash(key);
45 | int index = (nodes.length - 1) & h;
46 | Node newNode = new Node(index, key, value);
47 | if (nodes[index] == null) {
48 | nodes[index] = newNode;
49 | } else {
50 | Node lastNode = nodes[index].getLastNode();
51 | lastNode.setNext(newNode);
52 | }
53 | }
54 |
55 | public Object get(Object key) {
56 | int h = hash(key);
57 | int index = (nodes.length-1) & h;
58 | Node startNode = nodes[index];
59 | if (startNode == null) {
60 | return null;
61 | } else if (startNode.getKey() == key) {
62 | return startNode.getValue();
63 | } else {
64 | Node node = startNode.getNode(key);
65 | if (node == null) {
66 | return null;
67 | }
68 | return node.getValue();
69 | }
70 | }
71 |
72 | /**
73 | * 计算hash值,即在数组中的索引,以后进行优化
74 | *
75 | * @param key
76 | * @return
77 | */
78 | public static final int hash(Object key) {
79 | int h;
80 | return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
81 | }
82 | }
83 |
84 | class Node {
85 | Object key;
86 | Object value;
87 | int index;
88 | Node next;
89 |
90 | public Node(int index, Object key, Object value) {
91 | this.key = key;
92 | this.value = value;
93 | this.index = index;
94 | }
95 |
96 | public boolean isLast() {
97 | return this.next == null;
98 | }
99 |
100 | /**
101 | * 获取链表中与key相同的节点
102 | *
103 | * @param key
104 | * @return
105 | */
106 | public Node getNode(Object key) {
107 | if (key == this.key) {
108 | return this;
109 | }
110 | if (next != null) {
111 | return next.getNode(key);
112 | }
113 | return null;
114 | }
115 |
116 | public Node getLastNode() {
117 | if (this.next == null) {
118 | return this;
119 | }
120 | return this.next.getLastNode();
121 | }
122 |
123 | public Node getNext() {
124 | return next;
125 | }
126 |
127 | public void setNext(Node next) {
128 | this.next = next;
129 | }
130 |
131 | public Object getKey() {
132 | return key;
133 | }
134 |
135 | public Object getValue() {
136 | return value;
137 | }
138 | }
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/datastructure/dijkstra/DijkstraTest.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.datastructure.dijkstra;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法。该算法被称为
8 | * 是“贪心算法”的成功典范。本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,
9 | * 并赋予java实现代码。
10 | * 参考博客https://www.cnblogs.com/junyuhuang/p/4544747.html
11 | */
12 | public class DijkstraTest {
13 |
14 | public static void main(String[] args){
15 | List vertexs = new ArrayList();
16 | Vertex a = new Vertex("A", 0);
17 | Vertex b = new Vertex("B");
18 | Vertex c = new Vertex("C");
19 | Vertex d = new Vertex("D");
20 | Vertex e = new Vertex("E");
21 | Vertex f = new Vertex("F");
22 | vertexs.add(a);
23 | vertexs.add(b);
24 | vertexs.add(c);
25 | vertexs.add(d);
26 | vertexs.add(e);
27 | vertexs.add(f);
28 | int[][] edges = {
29 | {Integer.MAX_VALUE,6,3,Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE},
30 | {6,Integer.MAX_VALUE,2,5,Integer.MAX_VALUE,Integer.MAX_VALUE},
31 | {3,2,Integer.MAX_VALUE,3,4,Integer.MAX_VALUE},
32 | {Integer.MAX_VALUE,5,3,Integer.MAX_VALUE,5,3},
33 | {Integer.MAX_VALUE,Integer.MAX_VALUE,4,5,Integer.MAX_VALUE,5},
34 | {Integer.MAX_VALUE,Integer.MAX_VALUE,Integer.MAX_VALUE,3,5,Integer.MAX_VALUE}
35 |
36 | };
37 | Graph graph = new Graph(vertexs, edges);
38 | graph.printGraph();
39 | graph.search();
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/datastructure/dijkstra/Graph.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.datastructure.dijkstra;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.PriorityQueue;
6 | import java.util.Queue;
7 |
8 | public class Graph {
9 |
10 | /*
11 | * 顶点
12 | */
13 | private List vertexs;
14 |
15 | /*
16 | * 边
17 | */
18 | private int[][] edges;
19 |
20 | /*
21 | * 没有访问的顶点
22 | */
23 | private Queue unVisited;
24 |
25 | public Graph(List vertexs, int[][] edges) {
26 | this.vertexs = vertexs;
27 | this.edges = edges;
28 | initUnVisited();
29 | }
30 |
31 | /*
32 | * 搜索各顶点最短路径
33 | */
34 | public void search(){
35 | while(!unVisited.isEmpty()){
36 | Vertex vertex = unVisited.element();
37 | //顶点已经计算出最短路径,设置为"已访问"
38 | vertex.setMarked(true);
39 | //获取所有"未访问"的邻居
40 | List neighbors = getNeighbors(vertex);
41 | //更新邻居的最短路径
42 | updatesDistance(vertex, neighbors);
43 | pop();
44 | }
45 | System.out.println("search over");
46 | }
47 |
48 | /*
49 | * 更新所有邻居的最短路径
50 | */
51 | private void updatesDistance(Vertex vertex, List neighbors){
52 | for(Vertex neighbor: neighbors){
53 | updateDistance(vertex, neighbor);
54 | }
55 | }
56 |
57 | /*
58 | * 更新邻居的最短路径
59 | */
60 | private void updateDistance(Vertex vertex, Vertex neighbor){
61 | int distance = getDistance(vertex, neighbor) + vertex.getPath();
62 | if(distance < neighbor.getPath()){
63 | neighbor.setPath(distance);
64 | }
65 | }
66 |
67 | /*
68 | * 初始化未访问顶点集合
69 | */
70 | private void initUnVisited() {
71 | unVisited = new PriorityQueue();
72 | for (Vertex v : vertexs) {
73 | unVisited.add(v);
74 | }
75 | }
76 |
77 | /*
78 | * 从未访问顶点集合中删除已找到最短路径的节点
79 | */
80 | private void pop() {
81 | unVisited.poll();
82 | }
83 |
84 | /*
85 | * 获取顶点到目标顶点的距离
86 | */
87 | private int getDistance(Vertex source, Vertex destination) {
88 | int sourceIndex = vertexs.indexOf(source);
89 | int destIndex = vertexs.indexOf(destination);
90 | return edges[sourceIndex][destIndex];
91 | }
92 |
93 | /*
94 | * 获取顶点所有(未访问的)邻居
95 | */
96 | private List getNeighbors(Vertex v) {
97 | List neighbors = new ArrayList();
98 | int position = vertexs.indexOf(v);
99 | Vertex neighbor = null;
100 | int distance;
101 | for (int i = 0; i < vertexs.size(); i++) {
102 | if (i == position) {
103 | //顶点本身,跳过
104 | continue;
105 | }
106 | distance = edges[position][i]; //到所有顶点的距离
107 | if (distance < Integer.MAX_VALUE) {
108 | //是邻居(有路径可达)
109 | neighbor = getVertex(i);
110 | if (!neighbor.isMarked()) {
111 | //如果邻居没有访问过,则加入list;
112 | neighbors.add(neighbor);
113 | }
114 | }
115 | }
116 | return neighbors;
117 | }
118 |
119 | /*
120 | * 根据顶点位置获取顶点
121 | */
122 | private Vertex getVertex(int index) {
123 | return vertexs.get(index);
124 | }
125 |
126 | /*
127 | * 打印图
128 | */
129 | public void printGraph() {
130 | int verNums = vertexs.size();
131 | for (int row = 0; row < verNums; row++) {
132 | for (int col = 0; col < verNums; col++) {
133 | if(Integer.MAX_VALUE == edges[row][col]){
134 | System.out.print("X");
135 | System.out.print(" ");
136 | continue;
137 | }
138 | System.out.print(edges[row][col]);
139 | System.out.print(" ");
140 | }
141 | System.out.println();
142 | }
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/datastructure/dijkstra/Vertex.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.datastructure.dijkstra;
2 |
3 | public class Vertex implements Comparable{
4 |
5 | /**
6 | * 节点名称(A,B,C,D)
7 | */
8 | private String name;
9 |
10 | /**
11 | * 最短路径长度
12 | */
13 | private int path;
14 |
15 | /**
16 | * 节点是否已经出列(是否已经处理完毕)
17 | */
18 | private boolean isMarked;
19 |
20 | public Vertex(String name){
21 | this.name = name;
22 | this.path = Integer.MAX_VALUE; //初始设置为无穷大
23 | this.setMarked(false);
24 | }
25 |
26 | public Vertex(String name, int path){
27 | this.name = name;
28 | this.path = path;
29 | this.setMarked(false);
30 | }
31 |
32 | @Override
33 | public int compareTo(Vertex o) {
34 | return o.path > path?-1:1;
35 | }
36 |
37 | public boolean isMarked() {
38 | return isMarked;
39 | }
40 |
41 | public void setMarked(boolean marked) {
42 | isMarked = marked;
43 | }
44 |
45 | public String getName() {
46 | return name;
47 | }
48 |
49 | public void setName(String name) {
50 | this.name = name;
51 | }
52 |
53 | public int getPath() {
54 | return path;
55 | }
56 |
57 | public void setPath(int path) {
58 | this.path = path;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/datastructure/heap/HeapSort.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.datastructure.heap;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * Created by on 2016/12/17.
7 | * 参考其它人的博客https://www.cnblogs.com/chengxiao/p/6129630.html
8 | * 堆排序demo
9 | */
10 | public class HeapSort {
11 | public static void main(String []args){
12 | int []arr = {9,8,7,6,5,4,3,2,1};
13 | sort(arr);
14 | System.out.println(Arrays.toString(arr));
15 | }
16 | public static void sort(int []arr){
17 | //1.构建大顶堆
18 | for(int i=arr.length/2-1;i>=0;i--){
19 | //从第一个非叶子结点从下至上,从右至左调整结构
20 | adjustHeap(arr,i,arr.length);
21 | }
22 | //2.调整堆结构+交换堆顶元素与末尾元素
23 | for(int j=arr.length-1;j>0;j--){
24 | swap(arr,0,j);//将堆顶元素与末尾元素进行交换
25 | adjustHeap(arr,0,j);//重新对堆进行调整
26 | }
27 |
28 | }
29 |
30 | /**
31 | * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上)
32 | * @param arr
33 | * @param i
34 | * @param length
35 | */
36 | public static void adjustHeap(int []arr,int i,int length){
37 | int temp = arr[i];//先取出当前元素i
38 | for(int k=i*2+1;ktemp){//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
43 | arr[i] = arr[k];
44 | i = k;
45 | }else{
46 | break;
47 | }
48 | }
49 | arr[i] = temp;//将temp值放到最终的位置
50 | }
51 |
52 | /**
53 | * 交换元素
54 | * @param arr
55 | * @param a
56 | * @param b
57 | */
58 | public static void swap(int []arr,int a ,int b){
59 | int temp=arr[a];
60 | arr[a] = arr[b];
61 | arr[b] = temp;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/datastructure/heap/MaxHeap.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.datastructure.heap;
2 |
3 | /**
4 | * 二叉堆(最大堆)
5 | *
6 | * @author skywang
7 | * @date 2014/03/07
8 | */
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | public class MaxHeap> {
14 |
15 | private List mHeap; // 队列(实际上是动态数组ArrayList的实例)
16 |
17 | public MaxHeap() {
18 | this.mHeap = new ArrayList();
19 | }
20 |
21 | /*
22 | * 最大堆的向下调整算法
23 | *
24 | * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
25 | *
26 | * 参数说明:
27 | * start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
28 | * end -- 截至范围(一般为数组中最后一个元素的索引)
29 | */
30 | protected void filterdown(int start, int end) {
31 | int c = start; // 当前(current)节点的位置
32 | int l = 2*c + 1; // 左(left)孩子的位置
33 | T tmp = mHeap.get(c); // 当前(current)节点的大小
34 |
35 | while(l <= end) {
36 | int cmp = mHeap.get(l).compareTo(mHeap.get(l+1));
37 | // "l"是左孩子,"l+1"是右孩子
38 | if(l < end && cmp<0)
39 | l++; // 左右两孩子中选择较大者,即mHeap[l+1]
40 | cmp = tmp.compareTo(mHeap.get(l));
41 | if(cmp >= 0)
42 | break; //调整结束
43 | else {
44 | mHeap.set(c, mHeap.get(l));
45 | c = l;
46 | l = 2*l + 1;
47 | }
48 | }
49 | mHeap.set(c, tmp);
50 | }
51 |
52 | /*
53 | * 删除最大堆中的data
54 | *
55 | * 返回值:
56 | * 0,成功
57 | * -1,失败
58 | */
59 | public int remove(T data) {
60 | // 如果"堆"已空,则返回-1
61 | if(mHeap.isEmpty() == true)
62 | return -1;
63 |
64 | // 获取data在数组中的索引
65 | int index = mHeap.indexOf(data);
66 | if (index==-1)
67 | return -1;
68 |
69 | int size = mHeap.size();
70 | mHeap.set(index, mHeap.get(size-1));// 用最后元素填补
71 | mHeap.remove(size - 1); // 删除最后的元素
72 |
73 | if (mHeap.size() > 1)
74 | filterdown(index, mHeap.size()-1); // 从index号位置开始自上向下调整为最小堆
75 |
76 | return 0;
77 | }
78 |
79 | /*
80 | * 最大堆的向上调整算法(从start开始向上直到0,调整堆)
81 | *
82 | * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
83 | *
84 | * 参数说明:
85 | * start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)
86 | */
87 | protected void filterup(int start) {
88 | int c = start; // 当前节点(current)的位置
89 | int p = (c-1)/2; // 父(parent)结点的位置
90 | T tmp = mHeap.get(c); // 当前节点(current)的大小
91 |
92 | while(c > 0) {
93 | int cmp = mHeap.get(p).compareTo(tmp);
94 | if(cmp >= 0)
95 | break;
96 | else {
97 | mHeap.set(c, mHeap.get(p));
98 | c = p;
99 | p = (p-1)/2;
100 | }
101 | }
102 | mHeap.set(c, tmp);
103 | }
104 |
105 | /*
106 | * 将data插入到二叉堆中
107 | */
108 | public void insert(T data) {
109 | int size = mHeap.size();
110 |
111 | mHeap.add(data); // 将"数组"插在表尾
112 | filterup(size); // 向上调整堆
113 | }
114 |
115 | @Override
116 | public String toString() {
117 | StringBuilder sb = new StringBuilder();
118 | for (int i=0; i tree=new MaxHeap();
128 |
129 | System.out.printf("== 依次添加: ");
130 | for(i=0; icurrentNode.getNext().setNext(currentNode);
11 | * @param head
12 | * @return
13 | */
14 | public static LinkedNode cycleReverse(LinkedNode head) {
15 | if (head == null || head.getNext() == null) {
16 | return head;
17 | }
18 |
19 | //专门记录下一个节点(依次判断下个节点是否为空)
20 | LinkedNode nextNode = head.getNext();
21 |
22 | //记录next的next用于下次循环使用
23 | LinkedNode temp = nextNode.getNext();
24 |
25 | //准备好第一个节点(第一个节点不需要去反转)
26 | head.setNext(null);
27 | LinkedNode finalNode = head;//最终返回的链表
28 |
29 |
30 | //如果下一个几点不为空,说明还有节点,则进行反转
31 | while (nextNode != null) {
32 | //记录元素,为了指针下移
33 | temp = nextNode.getNext();
34 |
35 | //反转链表
36 | nextNode.setNext(finalNode);
37 | finalNode = nextNode;
38 |
39 | //指针下移
40 | nextNode = temp;
41 | }
42 |
43 | return finalNode;
44 | }
45 |
46 | public static void main(String[] args) {
47 | LinkedNode head = new LinkedNode(0);
48 | LinkedNode next = head.getNext();
49 | for (int i =1; i < 6; i++) {
50 | LinkedNode node = new LinkedNode(i);
51 | if (i==1) {
52 | head.setNext(node);
53 | next = node;
54 | } else {
55 | next.setNext(node);
56 | next = node;
57 | }
58 | }
59 |
60 | LinkedNode x = head;
61 | System.out.println("--printCurrentLinkedLsit---");
62 | for (int i= 0; i < 6; i++) {
63 | System.out.println("node:" + x);
64 | x = x.getNext();
65 | }
66 |
67 | // 反转单链表
68 | head = cycleReverse(head);
69 |
70 | LinkedNode x1 = head;
71 | System.out.println("--printCurrentLinkedLsit---");
72 | for (int i= 0; i < 6; i++) {
73 | System.out.println("node:" + x1);
74 | x1 = x1.getNext();
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/exam/FindKMax.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.exam;
2 |
3 | /**
4 | * 快速排序的实现
5 | * 寻找第K大的数
6 | */
7 | public class FindKMax {
8 |
9 | public static void main(String[] args) {
10 | // 排序后顺序:下标 0, 1, 2, 3, 4, 5, 6, 7
11 | // 0, 2, 6, 7, 8 , 12, 35, 90
12 | int[] array = {12, 8, 90, 35, 0, 7, 2, 6};
13 | int findK = 8;
14 | int index = findKMaxInteger(array, 0, array.length - 1, findK);
15 | System.out.println("maxK index:" + index + ",array[" + index + "]=" + array[index]);
16 | }
17 |
18 | public static int findKMaxInteger(int[] a, int low, int high, int k) {
19 | int n = a.length;
20 | if (low >= high || k > n)//边界条件和特殊输入的处理
21 | return 0;
22 | int pos = partition(a, low, high);
23 | while (pos != n - k) {
24 | if (pos > n - k) {
25 | high = pos - 1;
26 | pos = partition(a, low, high);
27 | }
28 | if (pos < n - k) {
29 | low = pos + 1;
30 | pos = partition(a, low, high);
31 | }
32 | }
33 | return pos;
34 | }
35 |
36 | private static int partition(int[] a, int low, int high) {
37 | //2, 初始化变量
38 | int i = low;
39 | int j = high;
40 | // 3. 保存key值
41 | int key = a[low];
42 |
43 | //4,完成一趟排序
44 | while (i < j) {
45 | //4.1 ,从右往左找到第一个小于key的数
46 | while (i < j && a[j] >= key) {
47 | j--;
48 | }
49 | // 4.2 从左往右找到第一个大于key的数
50 | while (i < j && a[i] <= key) {
51 | i++;
52 | }
53 |
54 | //4.3 交换
55 | if (i < j) {
56 | int temp = a[i];
57 | a[i] = a[j];
58 | a[j] = temp;
59 | }
60 | }
61 |
62 | // 4.4,调整key的位置, 把a[i]与a[low](等于key)交换值
63 | int temp = a[i];
64 | a[i] = a[low];
65 | a[low] = temp;
66 | return i;
67 | }
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/exam/FindKMaxOld.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.exam;
2 |
3 | /**
4 | * 在N个乱序元素的数组中找第K大的数
5 | * 思路:使用快速排序实现
6 | */
7 | public class FindKMaxOld {
8 | public static int findKMaxInteger(int array[], int low, int high, int findK) {
9 | int i = low;
10 | int j = high;
11 | int key = array[i];
12 |
13 | // int delta = high - low;
14 | // if (delta == 0 || delta == 1 || delta == -1) {
15 | // if (findK == 1) {
16 | // return high;
17 | // }
18 | // }
19 | while (i < j) {
20 | while (i < j && array[j] >= key)
21 | j--;
22 | array[i] = array[j];
23 |
24 | while (i < j && array[i] <= key)
25 | i++;
26 | array[j] = array[i];
27 |
28 | array[i] = key;
29 | }
30 |
31 |
32 | if (array.length - i < findK) {
33 | // return findKMaxInteger(array, low, i - 1, findK - (array.length - i));
34 |
35 | return findKMaxInteger(array, low, i - 1, findK);
36 | // 或者少使用一对小括号
37 | // return findKMaxInteger(array, low, i - 1, findK + i - array.length);
38 | // 参考 https://blog.csdn.net/u010412301/article/details/67704530
39 | } else if (array.length - i > findK) {
40 | return findKMaxInteger(array, i+1, high, findK);
41 | } else {
42 | return i;
43 | }
44 | }
45 |
46 | public static void main(String[] args) {
47 |
48 | // 排序后顺序:下标 0, 1, 2, 3, 4, 5, 6, 7
49 | // 0, 2, 6, 7, 8 , 12, 35, 90
50 | int[] array = {90, 8, 35, 12, 0, 7, 2, 6};
51 | int findK =4;
52 | int index = findKMaxInteger(array, 0, array.length - 1, findK);
53 | System.out.println("maxK index:" + index + ",array[" + index + "]=" + array[index]);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/exam/Jinchansushu.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.exam;
2 |
3 |
4 | /**
5 | * 金蝉素数-找出所有的5位数的金蝉素数
6 | *
7 | * 专家研究发现:这些数是由1,3,5,7,9 这5 个奇数字排列组成的5 位素数,且同时去掉它的最高位与最低位数字后
8 | * 的三位数还是素数,同时去掉它
9 | * 的高二位与低二位数字后的一位数还是素数。因此,人们把这些神秘的素数称为金蝉素数,喻意金蝉脱壳之后仍为美丽的金蝉。
10 | */
11 | public class Jinchansushu {
12 |
13 | public static void main(String[] Args) {
14 |
15 | int[] a = new int[6];
16 | for (int i = 13579; i <= 97531; i += 2) { //设置范围
17 | int t = 0; //标志,0代表素数,1代表不是素数
18 | for (int j = 3; j <= Math.sqrt(i); j += 2) { //判断是不是素数
19 | if (i % j == 0) {
20 | t = 1; //修改标志
21 | break;
22 | }
23 | }
24 |
25 |
26 | a[1] = i / 10000; //万分位
27 | a[2] = (i / 1000) % 10; //千分位
28 | a[3] = (i / 100) % 10; //百分位
29 | a[4] = (i / 10) % 10; //十分位
30 | a[5] = i % 10; //个位
31 |
32 | if (t == 0) {
33 | for (int x = 1; x <= 5; x++) { //筛选调是偶数的数字
34 | if (a[x] % 2 == 0) {
35 | t = 1;
36 | break;
37 | }
38 | }
39 | }
40 |
41 | if (t == 0) {
42 | for (int x = 1; x <= 4; x++) { //比较 ,确保没有相同的数字
43 | for (int y = x + 1; y <= 5; y++) {
44 | if (a[x] == a[y]) {
45 | t = 1;
46 | break;
47 | }
48 | }
49 | }
50 | }
51 |
52 |
53 | if (t == 0) { //确保中间的数字不是1或9 因为不是素数
54 | if (a[3] == 1 || a[3] == 9) {
55 | t = 1;
56 | }
57 | }
58 | if (t == 0) {
59 | int num = a[2] * 100 + a[3] * 10 + a[4];
60 | for (int j = 3; j <= Math.sqrt(num); j++) { //确保去掉最高位和最低位还是素数
61 | if (num % j == 0) {
62 | t = 1;
63 | break;
64 | }
65 | }
66 | }
67 |
68 | if (t == 0) {
69 | System.out.println(i); //如果是素数 输出该数字
70 | }
71 | }
72 |
73 | }
74 | }
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/exam/PerfectNumber.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.exam;
2 |
3 | public class PerfectNumber {
4 |
5 | /**
6 | * 1000以内的完数(完美数)完数:一个数恰好等于它的因子之和(因子:除去这个数本身的正约数).
7 | 例如:6=1+2+3.
8 | * @param args
9 | */
10 | public static void main(String[] args) {
11 | int sum = 0;
12 | for (int i = 1; i <= 1000; i++) {
13 | for (int j = 1; j < i; j++) {
14 | if (i % j == 0) {
15 | sum += j;
16 | }
17 | }
18 | if (sum == i) {
19 | System.out.println(i);
20 | }
21 | sum = 0;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/exam/SushuTest.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.exam;
2 |
3 | /**
4 | * 3~100的所有素数
5 | * 质数(prime number)又称素数,有无限个。
6 | * 质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
7 | */
8 | public class SushuTest {
9 | public static void main(String[] args) {
10 | int i,n,k=0;
11 | for (n = 3; n<=100; n++) { //3~100的所有数
12 | i=2;
13 | while (i arr[high] || low > high) {
15 | return -1;
16 | }
17 |
18 | int middle = (low + high) / 2; //初始中间位置
19 | if (arr[middle] > key) {
20 | //比关键字大则关键字在左区域
21 | return recursionBinarySearch(arr, key, low, middle - 1);
22 | } else if (arr[middle] < key) {
23 | //比关键字小则关键字在右区域
24 | return recursionBinarySearch(arr, key, middle + 1, high);
25 | } else {
26 | return middle;
27 | }
28 |
29 | }
30 |
31 | /**
32 | * 不使用递归的二分查找
33 | * title:commonBinarySearch
34 | *
35 | * @param arr
36 | * @param key
37 | * @return 关键字位置
38 | */
39 | public static int commonBinarySearch(int[] arr, int key) {
40 | int low = 0;
41 | int high = arr.length - 1;
42 | int middle = 0; //定义middle
43 |
44 | if (key < arr[low] || key > arr[high] || low > high) {
45 | return -1;
46 | }
47 |
48 | while (low <= high) {
49 | middle = (low + high) / 2;
50 | if (arr[middle] > key) {
51 | //比关键字大则关键字在左区域
52 | high = middle - 1;
53 | } else if (arr[middle] < key) {
54 | //比关键字小则关键字在右区域
55 | low = middle + 1;
56 | } else {
57 | return middle;
58 | }
59 | }
60 |
61 | return -1; //最后仍然没有找到,则返回-1
62 | }
63 |
64 |
65 | public static void main(String[] args) {
66 |
67 | int[] arr = {1, 3, 5, 7, 9, 11};
68 | int key = 5;
69 | // int position = recursionBinarySearch(arr,key,0,arr.length - 1);
70 |
71 | int position = commonBinarySearch(arr, key);
72 |
73 | if (position == -1) {
74 | System.out.println("查找的是" + key + ",序列中没有该数!");
75 | } else {
76 | System.out.println("查找的是" + key + ",找到位置为:" + position);
77 | }
78 |
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/search/FibonacciSearch.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.search;
2 |
3 | import java.util.Arrays;
4 |
5 | /*
6 | *----- 斐波那契查找------
7 | * 1.斐波那契实在二分查找基础上,用斐波那契数列来进行分割
8 | * 2.在斐波那契数列上找一个略大于查找元素表个数的值f(n)
9 | * 3.将查找元素表个数扩充到f(n) 如果要补充元素用最后一个元素补充
10 | * 4.完成后对f(n)个元素进行斐波那契分割,即分割成 前面f(n-1)个元素,后面f(n-2)个元素
11 | * 5.对要查找元素的那个部分进行递归
12 | * 6.就平均性能而言 优于折半查找 但是若一直在左边长半区查找则低于折半查找
13 | *
14 | * 参考文章https://blog.csdn.net/qq_41056506/article/details/81874439
15 | *
16 | * 避免递归(子函数嵌套多,导致栈溢出, 改成用迭代-for循环
17 | * 采用https://www.jb51.net/article/45596.htm
18 | * 里面的方法三
19 | * */
20 | public class FibonacciSearch {
21 | private static int maxsize = 20;
22 |
23 | //生成斐波那契数列
24 | public static int[] fibonacci() {
25 | int[] f = new int[maxsize];
26 | f[0] = 1;
27 | f[1] = 1;
28 | for (int i = 2; i < maxsize; i++) {
29 | f[i] = f[i - 1] + f[i - 2];
30 | }
31 | return f;
32 | }
33 |
34 | //查找
35 | public static int search(int[] a, int key) {
36 | int low = 0;
37 | int high = a.length - 1;
38 | int k = 0; //斐波那契分割数值下标
39 | int mid = 0;
40 | int f[] = fibonacci(); //获得斐波那契数列
41 | //获得斐波那契分割数值下标
42 | while (high > f[k] - 1) {
43 | k++;
44 | }
45 |
46 | //利用Java工具类Arrays 构造新数组并指向 数组 a[]
47 | int[] temp = Arrays.copyOf(a, f[k]);
48 |
49 | //对新构造的数组进行 元素补充
50 | for (int i = high + 1; i < temp.length; i++) {
51 | temp[i] = a[high];
52 | }
53 |
54 | while (low <= high) {
55 | //由于前面部分有f[k-1]个元素
56 | mid = low + f[k - 1] - 1;
57 | if (key < temp[mid]) {//关键字小于切割位置元素 继续在前部分查找
58 | high = mid - 1;
59 | /*全部元素=前部元素+后部元素
60 | * f[k]=f[k-1]+f[k-2]
61 | * 因为前部有f[k-1]个元素,所以可以继续拆分f[k-1]=f[k-2]+f[k-3]
62 | * 即在f[k-1]的前部继续查找 所以k--
63 | * 即下次循环 mid=f[k-1-1]-1
64 | * */
65 | k--;
66 | } else if (key > temp[mid]) {//关键字大于切个位置元素 则查找后半部分
67 | low = mid + 1;
68 | /*全部元素=前部元素+后部元素
69 | * f[k]=f[k-1]+f[k-2]
70 | * 因为后部有f[k-2]个元素,所以可以继续拆分f[k-2]=f[k-3]+f[k-4]
71 | * 即在f[k-2]的前部继续查找 所以k-=2
72 | * 即下次循环 mid=f[k-1-2]-1
73 | * */
74 | k -= 2;
75 | } else {
76 | if (mid <= high) {
77 | return mid;
78 | } else {
79 | return high;
80 | }
81 | }
82 | }
83 | return -1;
84 | }
85 |
86 | public static void main(String[] args) {
87 | int[] a = {1, 3, 5, 7, 9, 11, 12};
88 | int i = search(a, 5);
89 | System.out.println("5在:" + (i + 1));
90 | int j = search(a, 12);
91 | System.out.println("12在:" + (j + 1));
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/sort/BubbleSort.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.sort;
2 |
3 | public class BubbleSort {
4 | public static void main(String[] args) {
5 | int source[] = new int[]{53, 27, 36, 15, 69, 42};
6 | System.out.print("初始关键字:");
7 | printArray(source);
8 | System.out.println("");
9 | doBubbleSort(source);
10 | System.out.print("\n\n排序后结果:");
11 | printArray(source);
12 | }
13 |
14 | private static void printArray(int[] source) {
15 | for (int i = 0; i < source.length; i++) {
16 | System.out.print("\t" + source[i]);
17 | }
18 | System.out.println();
19 | }
20 |
21 | private static void doBubbleSort(int[] source) {
22 | for (int i = 0; i < source.length; i++) {
23 | for (int j = 0; j < source.length - i - 1; j++) {
24 | if (source[j] > source[j + 1]) {
25 | int tmp = source[j];
26 | source[j] = source[j + 1];
27 | source[j + 1] = tmp;
28 | }
29 | }
30 |
31 | if (i < source.length - 1) {
32 | System.out.print("第" + (i + 1) + "趟排序:");
33 | printArray(source);
34 | }
35 | }
36 |
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/sort/BucketSort.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.sort;
2 |
3 | import java.util.LinkedList;
4 |
5 | /**
6 | * 桶排序
7 | * 桶排序假设输入元素均匀而独立的分布在区间[0,1)上;
8 | * 桶排序的核心思想是,将[0,1)分为n个大小相同的子区间,
9 | * 上一个区间里的元素都比下一个区间里的元素小,然后对
10 | * 所有区间里的元素排序,最后顺序输出所有区间里的元素,
11 | * 达到对所有元素排序的目的。
12 | *
13 | * @author liushaoming
14 | */
15 | public class BucketSort {
16 | public void sort(Double[] a) {
17 | int n = a.length;
18 |
19 | /**
20 | * 创建链表(桶)集合并初始化,集合中的链表用于存放相应的元素
21 | */
22 | int bucketNum = 10; // 桶数
23 | LinkedList> buckets = new LinkedList>();
24 | for (int i = 0; i < bucketNum; i++) {
25 | LinkedList bucket = new LinkedList();
26 | buckets.add(bucket);
27 | }
28 | // 把元素放进相应的桶中
29 | for (int i = 0; i < n; i++) {
30 | int index = (int) (a[i] * bucketNum);
31 | buckets.get(index).add(a[i]);
32 | }
33 | // 对每个桶中的元素排序,并放进a中
34 | int index = 0;
35 | for (LinkedList linkedList : buckets) {
36 | int size = linkedList.size();
37 | if (size == 0) {
38 | continue;
39 | }
40 | /**
41 | * 把LinkedList转化为Double[]的原因是,之前已经实现了
42 | * 对数组进行排序的算法
43 | */
44 | Double[] temp = new Double[size];
45 | for (int i = 0; i < temp.length; i++) {
46 | temp[i] = linkedList.get(i);
47 | }
48 | // 利用插入排序对temp排序
49 | // TODO 这里忽略掉插入排序, 使用任何一种比较排序的实现都可以
50 | // new InsertSort().sort(temp);
51 | for (int i = 0; i < temp.length; i++) {
52 | a[index] = temp[i];
53 | index++;
54 | }
55 | }
56 |
57 | }
58 |
59 | public static void main(String[] args) {
60 | Double[] a = new Double[]{0.3, 0.6, 0.5};
61 | new BucketSort().sort(a);
62 | for (int i = 0; i < a.length; i++) {
63 | System.out.println(a[i]);
64 | }
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/sort/InsertSort.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.sort;
2 |
3 | /**
4 | * 插入排序
5 | * 所谓插入排序法,就是检查第i个数字,如果在它的左边的数字比它大,进行交换,这个动作一直继续下去,直到这个数字的左边数字比它还要小,就可以停止了。插入排序法主要的回圈有两个变数:i和j,每一次执行这个回圈,就会将第i个数字放到左边恰当的位置去。
6 | * 二、算法描述
7 | *
8 | * 1、从第一个元素开始,该元素可以认为已经被排序。
9 | * 2、取出下一个元素,在已经排序的元素序列中从后向前扫描。
10 | * 3、如果该元素(已排序)大于新元素,则将该元素移到下一位置。
11 | * 4、重复步骤3,直到找到已排序的元素小于或者等于新元素的位置。
12 | * 5、将新元素插入到该位置。
13 | * 6、重复步骤2。
14 | *
15 | * 三、效率分析
16 | *
17 | * 如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况如下。
18 | * 最好情况:序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。
19 | * 最坏情况:序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。
20 | * 直接插入排序属于稳定的排序,最坏时间复杂度为O(n^2),最好时间复杂度为O(n),空间复杂度为O(1)。
21 | * 插入排序的赋值操作是比较操作的次数加上(n-1)次。
22 | * 因此,插入排序不适合对于数据量比较大的排序应用。
23 | */
24 | public class InsertSort {
25 | public static void doInsertSort(int[] source) {
26 | int i, j;
27 | int insertNode;// 要插入的数据
28 | // 从数组的第二个元素开始循环将数组中的元素插入
29 | for (i = 1; i < source.length; i++) {
30 | // 设置数组中的第2个元素为第一次循环要插入的数据
31 | insertNode = source[i];
32 | j = i - 1;
33 | // 如果要插入的元素小于第j个元素,就将第j个元素向后移
34 | while ((j >= 0) && insertNode < source[j]) {
35 | source[j + 1] = source[j];
36 | j--;
37 | }
38 | // 直到要插入的元素不小于第j个元素,将insertNote插入到数组中
39 | source[j + 1] = insertNode;
40 | System.out.print("第" + i + "趟排序:");
41 | printArray(source);
42 | }
43 | }
44 |
45 | private static void printArray(int[] source) {
46 | for (int i = 0; i < source.length; i++) {
47 | System.out.print("\t" + source[i]);
48 | }
49 | System.out.println();
50 | }
51 |
52 | public static void main(String[] args) {
53 | int source[] = new int[]{53, 27, 36, 15, 69, 42};
54 | System.out.print("初始关键字:");
55 | printArray(source);
56 | System.out.println("");
57 | doInsertSort(source);
58 |
59 | System.out.print("\n\n排序后结果:");
60 | printArray(source);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/sort/MergeSort.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.sort;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * 归并排序-包括二路归并排序和多路归并排序,这里实现的是二路归并排序
7 | * 归并排序采用了分治法策略
8 | * 参考文档 https://www.cnblogs.com/chengxiao/p/6194356.html
9 | */
10 | public class MergeSort {
11 | public static void main(String[] args) {
12 | int[] arr = {9, 8, 7, 6, 5, 4, 3, 2, 1};
13 | sort(arr);
14 | System.out.println(Arrays.toString(arr));
15 | }
16 |
17 | public static void sort(int[] arr) {
18 | int[] temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
19 | sort(arr, 0, arr.length - 1, temp);
20 | }
21 |
22 | private static void sort(int[] arr, int left, int right, int[] temp) {
23 | if (left < right) {
24 | int mid = (left + right) / 2;
25 | sort(arr, left, mid, temp);//左边归并排序,使得左子序列有序
26 | sort(arr, mid + 1, right, temp);//右边归并排序,使得右子序列有序
27 | merge(arr, left, mid, right, temp);//将两个有序子数组合并操作
28 | }
29 | }
30 |
31 | private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
32 | int i = left;//左序列指针
33 | int j = mid + 1;//右序列指针
34 | int t = 0;//临时数组指针
35 | while (i <= mid && j <= right) {
36 | if (arr[i] <= arr[j]) { // 这里判断条件带上arr[i]==arr[j]是为了保证排序的稳定性(关键字相等的情况下,原来
37 | // 在左边的元素,排序后仍然在左边
38 | temp[t++] = arr[i++];
39 | } else {
40 | temp[t++] = arr[j++];
41 | }
42 | }
43 | while (i <= mid) {//将左边剩余元素填充进temp中
44 | temp[t++] = arr[i++];
45 | }
46 | while (j <= right) {//将右序列剩余元素填充进temp中
47 | temp[t++] = arr[j++];
48 | }
49 | t = 0;
50 | //将temp中的元素全部拷贝到原数组中
51 | while (left <= right) {
52 | arr[left++] = temp[t++];
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/sort/QuickSort.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.sort;
2 |
3 | /**
4 | * 快速排序,顾名思义,是一种速度快,效率高的排序算法。
5 | * 快排原理:
6 | * 在要排的数(比如数组A)中选择一个中心值key(比如A[0]),通过一趟排序将数组A分成两部分,其中以key为中心,key右边都比key大,key左边的都key小,然后对这两部分分别重复这个过程,直到整个有序。
7 | * 整个快排的过程就简化为了一趟排序的过程,然后递归调用就行了。
8 | * 一趟排序的方法:
9 | * 1,定义i=0,j=A.lenght-1,i为第一个数的下标,j为最后一个数下标
10 | * 2,从数组的最后一个数Aj从右往左找,找到第一小于key的数,记为Aj;
11 | * 3,从数组的第一个数Ai 从左往右找,找到第一个大于key的数,记为Ai;
12 | * 4,交换Ai 和Aj
13 | * 5,重复这个过程,直到 i=j
14 | * 6,调整key的位置,把A[i] 和key交换
15 | * 假设要排的数组为:A[8] ={ 5 2 8 9 2 3 4 9 }
16 | * 选择 key = 5, 开始时 i=0,j=7
17 | * index 0 1 2 3 4 5 6 7
18 | *
19 | * 开始: 5 2 8 9 2 3 4 9
20 | * i j
21 | * 第一次找 5 2 8 9 2 3 4 9
22 | * i j
23 | * 交换: 5 2 4 9 2 3 8 9
24 | * i j
25 | * 第二次找 5 2 4 9 2 3 8 9
26 | * i j
27 | * 交换: 5 2 4 3 2 9 8 9
28 | * i j
29 | * 第三次找 5 2 4 3 2 9 8 9
30 | * ij
31 | * 调整key: 2 5 4 3 5 9 8 9
32 | * ij
33 | * ---------------------
34 | * 作者:Yexiaofen
35 | * 来源:CSDN
36 | * 原文:https://blog.csdn.net/Yexiaofen/article/details/78018204
37 | * 版权声明:本文为博主原创文章,转载请附上博文链接!
38 | */
39 | public class QuickSort {
40 |
41 | public static void main(String[] args) {
42 | System.out.println("Hello World");
43 | int[] a = {12, 20, 5, 16, 15, 1, 30, 45, 23, 9};
44 | int start = 0;
45 | int end = a.length - 1;
46 | sort(a, start, end);
47 | for (int i = 0; i < a.length; i++) {
48 | System.out.println(a[i]);
49 | }
50 | }
51 |
52 | public static void sort(int[] a, int low, int high) {
53 | int start = low;
54 | int end = high;
55 | int key = a[low];
56 |
57 | while (end > start) {
58 | //从后往前比较
59 | while (end > start && a[end] >= key) //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
60 | end--;
61 | if (a[end] <= key) {
62 | int temp = a[end];
63 | a[end] = a[start];
64 | a[start] = temp;
65 | }
66 | //从前往后比较
67 | while (end > start && a[start] <= key)//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
68 | start++;
69 | if (a[start] >= key) {
70 | int temp = a[start];
71 | a[start] = a[end];
72 | a[end] = temp;
73 | }
74 | //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
75 | }
76 |
77 | //递归
78 | if (start > low) sort(a, low, start - 1);//左边序列。第一个索引位置到关键值索引-1
79 | if (end < high) sort(a, end + 1, high);//右边序列。从关键值索引+1到最后一个
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/sort/QuickSortSimple.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.sort;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * 快速排序,java的最简单实现
7 | * https://blog.csdn.net/Yexiaofen/article/details/78018204
8 | */
9 | public class QuickSortSimple {
10 |
11 | public static void main(String[] args) {
12 | int[] a = {12, 20, 5, 16, 15, 1, 30, 45, 23, 9};
13 | System.out.println(Arrays.toString(a));
14 | int start = 0;
15 | int end = a.length - 1;
16 | System.out.println("Start to sort...");
17 | sort(a, start, end);
18 | System.out.println(Arrays.toString(a));
19 | }
20 |
21 | private static void sort(int[] a, int low, int high) {
22 | //1,找到递归算法的出口
23 | if (low > high) {
24 | return;
25 | }
26 |
27 | //2, 初始化变量
28 | int i = low;
29 | int j = high;
30 | // 3. 保存key值
31 | int key = a[low];
32 |
33 | //4,完成一趟排序
34 | while (i < j) {
35 | //4.1 ,从右往左找到第一个小于key的数
36 | while (i < j && a[j] >= key) {
37 | j--;
38 | }
39 | // 4.2 从左往右找到第一个大于key的数
40 | while (i < j && a[i] <= key) {
41 | i++;
42 | }
43 |
44 | //4.3 交换
45 | if (i < j) {
46 | int temp = a[i];
47 | a[i] = a[j];
48 | a[j] = temp;
49 | }
50 | }
51 |
52 | // 4.4,调整key的位置, 把a[i]与a[low](等于key)交换值
53 | int temp = a[i];
54 | a[i] = a[low];
55 | a[low] = temp;
56 |
57 | //5, 对key左边的数快排
58 | sort(a, low, i - 1);
59 | //5, 对key左边的数快排
60 | sort(a, i + 1, high);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/sort/SelectionSort.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.sort;
2 |
3 | /**
4 | * 选择排序
5 | * a) 原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。也就是:
6 | * 每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。
7 | * 基于此思想的算法主要有简单选择排序、树型选择排序和堆排序。(这里只介绍常用的简单选择排序)
8 | * 堆排序参考 {@link com.appjishu.algorithm4j.datastructure.heap.HeapSort }
9 | *
10 | * b) 简单选择排序的基本思想:给定数组:
11 | * int[] arr={里面n个数据};第1趟排序,在待排序数据arr[1]~arr[n]中选出最小的数据,
12 | * 将它与arrr[1]交换;第2趟,在待排序数据arr[2]~arr[n]中选出最小的数据,将它与r[2]交换;
13 | * 以此类推,第i趟在待排序数据arr[i]~arr[n]中选出最小的数据,将它与r[i]交换,直到全部排序完成。
14 | */
15 | public class SelectionSort {
16 | public static void main(String[] args) {
17 | int[] arr = {1, 3, 2, 45, 65, 33, 12};
18 | System.out.println("交换之前:");
19 | for (int num : arr) {
20 | System.out.print(num + " ");
21 | }
22 | //选择排序的优化
23 | for (int i = 0; i < arr.length - 1; i++) {// 做第i趟排序
24 | int k = i;
25 | for (int j = k + 1; j < arr.length; j++) {// 选最小的记录
26 | if (arr[j] < arr[k]) {
27 | k = j; //记下目前找到的最小值所在的位置
28 | }
29 | }
30 | //在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换
31 | if (i != k) { //交换a[i]和a[k]
32 | int temp = arr[i];
33 | arr[i] = arr[k];
34 | arr[k] = temp;
35 | }
36 | }
37 | System.out.println();
38 | System.out.println("交换后:");
39 | for (int num : arr) {
40 | System.out.print(num + " ");
41 | }
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/algorithm4j/sort/ShellSort.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.algorithm4j.sort;
2 |
3 | import java.util.Arrays;
4 |
5 | /**
6 | * 希尔排序-插入排序的一种
7 | * 参考了大神的文档https://www.cnblogs.com/chengxiao/p/6104371.html
8 | */
9 | public class ShellSort {
10 | public static void main(String []args){
11 | int []arr ={1,4,2,7,9,8,3,6};
12 | sort(arr);
13 | System.out.println(Arrays.toString(arr));
14 |
15 | // int []arr1 ={1,4,2,7,9,8,3,6};
16 | // sort1(arr1);
17 | // System.out.println(Arrays.toString(arr1));
18 | }
19 |
20 | /**
21 | * 希尔排序 针对有序序列在插入时采用交换法
22 | * @param arr
23 | */
24 | public static void sort(int []arr){
25 | //增量gap,并逐步缩小增量
26 | for(int gap=arr.length/2;gap>0;gap/=2){
27 | //从第gap个元素,逐个对其所在组进行直接插入排序操作
28 | for(int i=gap;i=0 && arr[j]0;gap/=2){
46 | //从第gap个元素,逐个对其所在组进行直接插入排序操作
47 | for(int i=gap;i=0 && temp f[k] - 1) {
24 | k++;
25 | }
26 |
27 | int[] temp = Arrays.copyOf(a, f[k]);
28 |
29 | //填充
30 | for (int j = high+1; j < temp.length; j++) {
31 | temp[j] = a[high];
32 | }
33 |
34 | while (low <= high) {
35 | // 前面部分有f[k-1] 个元素
36 | int mid = low + f[k-1] - 1;
37 | if (key < temp[mid]) {
38 | high = mid - 1;
39 | k--;
40 | } else if (key > temp[mid]) {
41 | low = mid + 1;
42 | k -= 2;
43 | } else {
44 | if (mid <= high) {
45 | return mid;
46 | } else {
47 | return high;
48 | }
49 | }
50 | }
51 |
52 | return -1;
53 | }
54 |
55 | private static int[] fibonacci() {
56 | int[] f = new int[maxsize];
57 | f[0] = 1;
58 | f[1] = 1;
59 | for (int i = 2; i < maxsize; i++) {
60 | f[i] = f[i - 1] + f[i - 2];
61 | }
62 | return f;
63 | }
64 |
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/appjishu/test/QuickSortTest.java:
--------------------------------------------------------------------------------
1 | package com.appjishu.test;
2 |
3 | public class QuickSortTest {
4 | public static void main(String[] args) {
5 | System.out.println("Hello World");
6 | int[] a = {12, 20, 5, 16, 15, 1, 30, 45, 23, 9};
7 | int start = 0;
8 | int end = a.length - 1;
9 | sort(a, start, end);
10 | for (int i = 0; i < a.length; i++) {
11 | System.out.println(a[i]);
12 | }
13 | }
14 |
15 | private static void sort(int[] a, int low, int high) {
16 | int start = low;
17 | int end = high;
18 | int key = a[low];
19 |
20 | while (end > start) {
21 | while(end > start && a[end] >= key)
22 | end--;
23 | if (a[end] <= key) {
24 | int temp = a[start];
25 | a[start] = a[end];
26 | a[end] = temp;
27 | }
28 |
29 | while (end > start && a[start] <= key)
30 | start++;
31 | if (a[start] >= key) {
32 |
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------