# java一些必会算法

1.O表示法：粗略的量度方法即算法的速度是如何与数据项的个数相关的

O(1)是最优秀的,O(logN)良好,O(N)还可以,O(N2)稍差(在冒泡法中见到)

2. 排序

 public class JWzw {    //插入排序    public void insertArray(Integer[] in ) {        int tem = 0;        int num = 0;        int upnum = 0;        for (int i = 0; i < in .length; i++) {            for (int j = i - 1; j >= 0; j--) {                num++;                if ( in [j + 1] < in [j]) {                    tem = in [j + 1]; in [j + 1] = in [j]; in [j] = tem;                    upnum++;                } else {                    break;                }            }        }        for (int i = 0; i < in .length; i++) {            System.out.print( in [i]);            if (i < in .length - 1) {                System.out.print(",");            }        }        System.out.println();        System.out.println("插入排序循环次数:" + num);        System.out.println("移动次数：" + upnum);        System.out.print("\n\n\n");    }    //选择排序    public void chooseArray(Integer[] in ) {        int tem = 0;        int num = 0;        int upnum = 0;        for (int i = 0; i < in .length; i++) {            for (int j = 0; j < in .length - 1; j++) {                num++;                if ( in [j + 1] < in [j]) {                    tem = in [j + 1]; in [j + 1] = in [j]; in [j] = tem;                    upnum++;                }            }        }        for (int i = 0; i < in .length; i++) {            System.out.print( in [i]);            if (i < in .length - 1) {                System.out.print(",");            }        }        System.out.println();        System.out.println("选择排序循环次数:" + num);        System.out.println("移动次数：" + upnum);        System.out.print("\n\n\n");    }    //冒泡排序    public void efferArray(Integer[] in ) {        int tem = 0;        int num = 0;        int upnum = 0;        for (int i = 0; i < in .length; i++) {            for (int j = i; j < in .length - 1; j++) {                num++;                if ( in [j + 1] < in [i]) {                    tem = in [j + 1]; in [j + 1] = in [i]; in [i] = tem;                    upnum++;                }            }        }        for (int i = 0; i < in .length; i++) {            System.out.print( in [i]);            if (i < in .length - 1) {                System.out.print(",");            }        }        System.out.println();        System.out.println("冒泡排序循环次数:" + num);        System.out.println("移动次数：" + upnum);        System.out.print("\n\n\n");    }    //打印乘法口诀    public void printMulti() {        for (int j = 1; j < 10; j++) {            for (int i = 1; i <= j; i++) {                System.out.print(i + " * " + j + " = " + j * i + "\t");            }            System.out.print("\t\n");        }        System.out.print("\n\n\n");    }    //打印N * 1 + N * 2 + N * 3 =num的所有组合    public void printNumAssemble(int num) {        for (int i = 0; i < num + 1; i++) {            for (int j = 0; j < num / 2 + 1; j++) {                for (int in = 0; in < num / 3 + 1; in ++) {                    if (i * 1 + j * 2 + in * 3 == num) {                        System.out.println("小马" + i + ",\t中马" + j + ",\t大马" + in );                    }                }            }        }    }    /** * @param args */    public static void main(String[] args) {        JWzw jwzw = new JWzw();        int num = 3;        jwzw.printMulti(); //打印乘法口诀        jwzw.printNumAssemble(100); //打印N * 1 + N * 2 + N * 3 =num的所有组合        Integer in [] = {            8, 89, 5, 84, 3, 45, 12, 33, 77, 98, 456, 878, 654, 213, 897        };        jwzw.efferArray( in ); //冒泡排序        Integer in1[] = {            8, 89, 5, 84, 3, 45, 12, 33, 77, 98, 456, 878, 654, 213, 897        };        jwzw.insertArray(in1); //插入排序        Integer in2[] = {            8, 89, 5, 84, 3, 45, 12, 33, 77, 98, 456, 878, 654, 213, 897        };        jwzw.chooseArray(in2); //选择排序        //int i = num++;        //System.out.println(i);        System.out.println(1000 >> 2);    }}

3. 优先级队列

class PriorityQueue {    private long[] a = null;    private int nItems = 0;    private int maxSize = 0;    public PriorityQueue(int maxSize) {        a = new long[maxSize];        this.maxSize = maxSize;        nItems = 0;    }    public void insert(long l) {        //优先级队列的插入不是队尾,而是选择一个合适的按照某种顺序插入的        //当队列长度为0时，如下        //不为0时,将所有比要插入的数小的数据后移,这样大的数就在队列的头部了        int i = 0;        if (nItems == 0) {            a[0] = l;        } else {            for (i = nItems - 1; i >= 0; i--) {                if (l < a[i]) a[i + 1] = a[i];                else break;            }            a[i + 1] = l;        }        nItems++;    }    public long remove() {        //移出的是数组最上端的数，这样减少数组元素的移动        return a[--nItems];    }    public boolean isEmpty() {        return (nItems == 0);    }    public boolean isFull() {        return (nItems == maxSize);    }    public int size() {        return nItems;    }}public class duilie { // 队列体类    private duilie s;    private String data;    duilie(String data) {        this.data = data;    }    public String getData() {        return data;    }    public void setData(String data) {        this.data = data;    }    public duilie getS() {        return s;    }    public void setS(duilie s) {        this.s = s;    }}public class duiliecz { // 队列操作类    /**  * @param args  */    private int i = 0; // 队列长    private duilie top = new duilie(""); // 队列头    private duilie end = new duilie(""); // 队列尾    public void add(String s) { // 添加队列        duilie m = new duilie(s);        if (i != 0) {            m.setS(top.getS());            top.setS(m);        } else {            top.setS(m);            end.setS(m);        }        i++;    }

4. 队列

public void del() { // 删除队尾    if (i == 0) {        return;    } else if (i == 1) {        top.setS(null);        end.setS(null);    } else {        duilie top1 = new duilie(""); // 队列底查找用缓存        top1.setS(top.getS());        while (!top1.getS().getS().equals(end.getS())) {            top1.setS(top1.getS().getS());        }        end.setS(top1.getS());    }    i--;}public static void main(String[] args) {    // TODO Auto-generated method stub    duiliecz m = new duiliecz();    m.add("1");    m.add("2");    m.add("3");    m.add("4");    for (int n = 0; n < 4; n++) {        m.del();    }}public int getI() {    return i;}public duilie getEnd() {    return end;}public duilie getTop() {    return top;}}

5.

public class Stack {    int[] arr;    int len = 0;    public Stack() {        arr = new int[100];    }    public Stack(int n) {        arr = new int[n];    }    public int size() {        return len + 1;    }    // 扩大数组    public void resize() {        int[] b = new int[arr.length * 2];        System.arraycopy(arr, 0, b, 0, arr.length);        arr = b;    }    public void show() {        for (int i = 0; i < len; i++) {            System.out.print(arr[i] + "  ");        }        System.out.println();    }    // 进栈    public void push(int a) {        if (len >= arr.length) resize();        arr[len] = a;        len++;    }    // 出栈    public int pop() {        if (len == 0) {            System.out.println();            System.out.println("stack is empty!");            return -1;        }        int a = arr[len - 1];        arr[len - 1] = 0;        len--;        return a;    }}

6. 链表

class Node {    Object data;    Node next;    public Node(Object data) {        setData(data);    }    public void setData(Object data) {        this.data = data;    }    public Object getData() {        return data;    }}class Link {    Node head;    int size = 0;    public void add(Object data) {        Node n = new Node(data);        if (head == null) {            head = n;        } else {            Node current = head;            while (true) {                if (current.next == null) {                    break;                }                current = current.next;            }            current.next = n;        }        size++;    }    public void show() {        Node current = head;        if (current != null) {            while (true) {                System.out.println(current);                if (current == null) {                    break;                }                current = current.next;            }        } else {            System.out.println("link is empty");        }    }    public Object get(int index) {        // ....    }    public int size() {        return size;    }}

7. 单链表

class Node // 节点类，单链表上的节点{    String data; // 数据域，存放String类的数据    Node next; // 指向下一个节点    Node(String data) {        this.data = data; // 构造函数    }    String get() {        return data; // 返回数据    }}class MyLinkList // 链表类{    Node first; // 头节点    int size; // 链表长度    MyLinkList(String arg[]) {        // Node first = new Node("head");//生成头节点        first = new Node("head"); // J.F. 这里不需要定义局部变量 first        // 如果定义了局部变量，那成员变量 first 就一直没有用上        // 所以，它一直为空        size = 0;        Node p = first;        for (int i = 0; i < arg.length; i++) // 将arg数组中的元素分别放入链表中        {            Node q = new Node(arg[i]);            q.next = p.next; // 每一个节点存放一个arg数组中的元素            p.next = q;            p = p.next;            size++;        }    }    MyLinkList() // 无参数构造函数    {        // Node first = new Node("head");        first = new Node("head"); // J.F. 这里犯了和上一个构造方法同样的错误        size = 0;    }    int size() // 返回链表长度    {        return size;    }    void insert(Node a, int index) // 将节点a 插入链表中的第index个位置    {        Node temp = first;        for (int i = 0; i < index; i++) {            temp = temp.next; // 找到插入节点的前一节点        }        a.next = temp.next; // 插入节点        temp.next = a;        size++;    }    Node del(int index) // 删除第index个节点，并返回该值    {        Node temp = first;        for (int i = 0; i < index; i++) {            temp = temp.next; // 找到被删除节点的前一节点        }        Node node = temp.next;        temp.next = node.next;        size--; // 删除该节点，链表长度减一        return node;    }    void print() // 在屏幕上输出该链表（这段程序总是出错，不知道错在哪里）    {        Node temp = first;        for (int i = 1; i < size; i++) // 将各个节点分别在屏幕上输出        {            temp = temp.next;            System.out.print(temp.get() + "->");        }    }    void reverse() // 倒置该链表    {        for (int i = 0; i < size; i++) {            insert(del(size - 1), 0); // 将最后一个节点插入到最前            // J.F. 最后一个节点的 index 应该是 size - 1            // 因为第一个节点的 index 是 0        }    }    String get(int index) // 查找第index个节点，返回其值    {        if (index >= size) {            return null;        }        Node temp = first;        for (int i = 0; i < index; i++) {            temp = temp.next; // 找到被查找节点的前一节点        }        return temp.next.get();    }}class MyStack // 堆栈类，用单链表实现{    MyLinkList tmp;    Node temp;    MyStack() {        // MyLinkList tmp = new MyLinkList();        tmp = new MyLinkList(); // J.F. 和 MyLinkList 构造方法同样的错误    }    void push(String a) // 压栈，即往链表首部插入一个节点    {        Node temp = new Node(a);        tmp.insert(temp, 0);    }    String pop() // 出栈，将链表第一个节点删除    {        Node a = tmp.del(0);        return a.get();    }    int size() {        return tmp.size();    }    boolean empty() // 判断堆栈是否为空    {        if (tmp.size() == 0) return false;        else return true;    }}public class MyLinkListTest // 测试程序部分{    public static void main(String arg[]) // 程序入口    {        if ((arg.length == 0) || (arg.length > 10)) System.out.println("长度超过限制或者缺少参数");        else {            MyLinkList ll = new MyLinkList(arg); // 创建一个链表            ll.print(); // 先输出该链表（运行到这一步抛出异常）            ll.reverse(); // 倒置该链表            ll.print(); // 再输出倒置后的链表            String data[] = new String[10];            int i;            for (i = 0; i < ll.size(); i++) {                data[i] = ll.get(i); // 将链表中的数据放入数组            }            // sort(data);// 按升序排列data中的数据（有没有现成的排序函数？）            for (i = 0; i < ll.size(); i++) {                System.out.print(data[i] + ";"); // 输出数组中元素            }            System.out.println();            MyStack s = new MyStack(); // 创建堆栈实例s            for (i = 0; i < ll.size(); i++) {                s.push(data[i]); // 将数组元素压栈            }            while (!s.empty()) {                System.out.print(s.pop() + ";"); // 再将堆栈里的元素弹出            }        }    }}

8. 双端链表

class Link {    public int iData = 0;    public Link next = null;    public Link(int iData) {        this.iData = iData;    }    public void display() {        System.out.print(iData + " ");    }}class FirstLastList {    private Link first = null;    private Link last = null;    public FirstLastList() {        first = null;        last = null;    }    public void insertFirst(int key) {        Link newLink = new Link(key);        if (this.isEmpty()) last = newLink;        newLink.next = first;        first = newLink;    }    public void insertLast(int key) {        Link newLink = new Link(key);        if (this.isEmpty()) first = newLink;        else last.next = newLink;        last = newLink;    }    public Link deleteFirst() {        Link temp = first;        if (first.next == null) last = null;        first = first.next;        return temp;    }    public boolean isEmpty() {        return (first == null);    }    public void displayList() {        System.out.print("List (first-->last): ");        Link current = first;        while (current != null) {            current.display();            current = current.next;        }        System.out.println("");    }}class FirstLastListApp {    public static void main(String[] args) {        // TODO Auto-generated method stub        FirstLastList theList = new FirstLastList();        theList.insertFirst(22); // insert at front        theList.insertFirst(44);        theList.insertFirst(66);        theList.insertLast(11); // insert at rear        theList.insertLast(33);        theList.insertLast(55);        theList.displayList(); // display the list        theList.deleteFirst(); // delete first two items        theList.deleteFirst();        theList.displayList(); // display again    }}

9. 有序链表

package arithmetic;class Link {    public int iData = 0;    public Link next = null;    public Link(int iData) {        this.iData = iData;    }    public void display() {        System.out.print(iData + " ");    }}class SortedList {    private Link first = null;    public SortedList() {        first = null;    }    public void insert(int key) {        Link newLink = new Link(key);        Link previous = null;        Link current = first;        // while的第一个条件是没有到达链表的尾端,第二个是按顺序找到一个合适的位置        while (current != null && key > current.iData) {            previous = current;            current = current.next;        }        // 如果是空表或者要插入的元素最小,则在表头插入key        if (current == first) first = newLink;        else previous.next = newLink;        newLink.next = current;    }    /** * 删除表头的节点 * * @return 要删除的节点 */    public Link remove() {        Link temp = first;        first = first.next;        return temp;    }    public boolean isEmpty() {        return (first == null);    }    public void displayList() {        System.out.print("List (first-->last): ");        Link current = first; // start at beginning of list        while (current != null) // until end of list,        {            current.display(); // print data            current = current.next; // move to next link        }        System.out.println("");    }}class SortedListApp {    public static void main(String[] args) { // create new list        SortedList theSortedList = new SortedList();        theSortedList.insert(20); // insert 2 items        theSortedList.insert(40);        theSortedList.displayList(); // display list        theSortedList.insert(10); // insert 3 more items        theSortedList.insert(30);        theSortedList.insert(50);        theSortedList.displayList(); // display list        theSortedList.remove(); // remove an item        theSortedList.displayList(); // display list    }}

10. 双向链表

class Link {    // 双向链表,有两个指针,一个向前,一个向后    public int iData = 0;    public Link previous = null;    public Link next = null;    public Link(int iData) {        this.iData = iData;    }    public void display() {        System.out.print(iData + " ");    }}class DoublyLinked {    // 分别指向链表的表头和表尾    private Link first = null;    private Link last = null;    public boolean isEmpty() {        return first == null;    }    /** * 在表头插入数据 * * @param 要插入的节点的数据 */    public void insertFirst(int key) {        Link newLink = new Link(key);        // 如果开始链表为空,则插入第一个数据后,last也指向第一个数据        if (this.isEmpty()) last = newLink;        else { // 表不为空的情况            first.previous = newLink;            newLink.next = first;        }        // 无论怎样,插入后都的让first重新指向第一个节点        first = newLink;    }    public void insertLast(int key) { // 在尾端插入数据,同上        Link newLink = new Link(key);        if (this.isEmpty()) first = newLink;        else {            last.next = newLink;            newLink.previous = last;        }        last = newLink;    }    /** * 在指定的节点后插入数据 * * @param key *            指定的节点的值 * @param iData *            要插入的数据 * @return 是否插入成功 */    public boolean insertAfter(int key, int iData) {        Link newLink = new Link(key);        Link current = first;        // 从first开始遍历,看能否找到以key为关键字的节点        while (current.iData != key) {            current = current.next;            // 若能找到就跳出循环,否则返回false,插入失败            if (current == null) return false;        }        // 如果插入点在last的位置        if (current == last) {            last = newLink;        } else { // 非last位置,交换各个next和previous的指针            newLink.next = current.next;            current.next.previous = newLink;        }        current.next = newLink;        newLink.previous = current;        return true;    }    /** * 删除表头的节点 * * @return */    public Link deleteFirst() {        Link temp = first;        // 如果表中只有一个元素,删除后则为空表,所以last=null        if (first.next == null) last = null;        else        // 否则,让第二个元素的previous=null            first.next.previous = null;        // 删除头指针,则first指向原来的second        first = first.next;        return temp;    }    public Link deleteLast() { // 同上        Link temp = last;        if (last.previous == null) first = null;        else last.previous.next = null;        last = last.previous;        return temp;    }    public Link deleteKey(int key) {        Link current = first;        // 遍历整个链表查找对应的key,如果查到跳出循环,否则...        while (current.iData != key) {            current = current.next;            // ...否则遍历到表尾,说明不存在此key,返回null,删除失败            if (current == null) return null;        }        if (current == first) first = first.next;        else current.previous.next = current.next;        if (current == last) last = last.previous;        else current.next.previous = current.previous;        return current;    }    public void displayForward() {        Link current = first;        while (current != null) {            current.display();            current = current.next;        }        System.out.println();    }    public void displayBackward() {        Link current = last;        while (current != null) {            current.display();            current = current.previous;        }        System.out.println();    }}class DoublyLinkedApp {    public static void main(String[] args) { // make a new list        DoublyLinked theList = new DoublyLinked();        theList.insertFirst(22); // insert at front        theList.insertFirst(44);        theList.insertFirst(66);        theList.insertLast(11); // insert at rear        theList.insertLast(33);        theList.insertLast(55);        theList.displayForward(); // display list forward        theList.displayBackward(); // display list backward        theList.deleteFirst(); // delete first item        theList.deleteLast(); // delete last item        theList.deleteKey(11); // delete item with key 11        theList.displayForward(); // display list forward        theList.insertAfter(22, 77); // insert 77 after 22        theList.insertAfter(33, 88); // insert 88 after 33        theList.displayForward(); // display list forward    }}

11. 实现二叉树前序遍历迭代器

class TreeNode这个类用来声明树的结点，其中有左子树、右子树和自身的内容。class MyTree这个类用来声明一棵树，传入根结点。这里设计的比较简单class TreeEum这个类是树的迭代器，通过 MyTree类的方法获取，这里主要就是设计它了。代码如下：//TreeNode类，使用了泛型，由于比较简单，考试.大提示不作解释　　 class TreeNode < E > {    E node;　　    private TreeNode < String > left;　　    private TreeNode < String > right;　　    public TreeNode(E e) {　　        this(e, null, null);    }　　    public TreeNode(E e, TreeNode < String > left, TreeNode < String > right) {　　        this.node = e;　　        this.left = left;　　        this.right = right;    }　　    public TreeNode < String > left() {　　        return left;    }　　    public TreeNode < String > right() {　　        return right;    }}// MyTree类，没什么功能，传入根结点构造，getEnumerator()方法获取迭代器。　　class MyTree {    TreeNode < String > root;　　    public MyTree(TreeNode < String > root) {　　        this.root = root;    }　　    public TreeEnum getEnumerator() {　　        return new TreeEnum(root);    }}// 这个类为迭代器，有详细解释，相信各位能看懂。在栈中用了两次泛型。　　import java.util.Stack;　　public class TreeEnum {　　    private TreeNode < String > root;　　    private Stack < TreeNode < String >> store; /* 保存遍历左子树但未遍历右子树的结点 */ 　　    private TreeNode < String > next;　　    public TreeEnum(TreeNode < String > root) {　　        this.root = root;        store = new Stack < TreeNode < String >> ();        next = root;    }　　    public TreeNode < String > next() {        TreeNode < String > current = next;　　        if (next != null) {            /* 如果当前结点的左子树不为空,则遍历左子树,并标记当前结点未遍历右子树 */            　　            if (next.left() != null) {                store.push(next);                next = next.left();            }            // 如果当前结点的左子树为空,则遍历右子树            　　            else if (next.right() != null) {                next = next.right();            }            /* 如果当前结点为叶子,则找未遍历右子树的结点并且遍历它的右子树 */            　　            else {　　                if (!store.empty()) /* 判断是否还有结点的右子树未遍历 */ {                    TreeNode < String > tmp = store.pop();                    /* 如果有未遍历右子树的结点,但它的右子树为空,且还有结点的右子树未遍历, */                    /* 则一直往上取,直到取到未遍历右子树且右子树不为空的结点,遍历它的右子树. */                    　　                    while ((tmp.right() == null) && !store.empty()) {                        tmp = store.pop();                    }                    next = tmp.right();                }　　                else {                    /* 如果没有哪个结点右子树未遍历,则表示没有下一个结点了,设置next为null */                    next = null;                }            }        }　　        return current;    }　　    public boolean hasMoreElement() {　　        return next != null;    }}　　下面写个测试类，不作解释，相信大家看得懂　　public class TreeReader {　　    public static void main(String[] args) {        TreeNode < String > n1 = new TreeNode < String > ("n1");        TreeNode < String > n2 = new TreeNode < String > ("n2");        TreeNode < String > n3 = new TreeNode < String > ("n3");        TreeNode < String > n4 = new TreeNode < String > ("n4");        TreeNode < String > n5 = new TreeNode < String > ("n5");        TreeNode < String > n6 = new TreeNode < String > ("n6", null, n1);        TreeNode < String > n7 = new TreeNode < String > ("n7", n2, null);        TreeNode < String > n8 = new TreeNode < String > ("n8", n7, null);        TreeNode < String > n9 = new TreeNode < String > ("n9", null, n5);        TreeNode < String > n10 = new TreeNode < String > ("n10", n4, n9);        TreeNode < String > n11 = new TreeNode < String > ("n11", n6, n8);        TreeNode < String > n12 = new TreeNode < String > ("n12", n3, n10);        TreeNode < String > root = new TreeNode < String > ("root", n11, n12);        MyTree tree = new MyTree(root);        TreeEnum eum = tree.getEnumerator();　　        while (eum.hasMoreElement()) {            System.out.print(eum.next().node + "--");        }        System.out.println("end");    }}

12. 迭代器

package TreeIterator;public interface Iterator {    public boolean hasNext();    public Object next();}这个接口我们有2个方法， hasNext()是否还有下一条数据， next返回具体的 Object这里也就是树。我们先不必要忙着做他的实现类，我们现在要来做的是这个容器（不是 JAVA中容器，与 arraylist什么的无关），正所谓树的容器是什么，是山也！我们想想山应该具有什么呢！？首先它要有种植树的功能，这里可以看作添加树。我们可以想像山的功能是和树相互关联的，那么他们之间是什么关系呢，我们给他们一种聚合的关系，聚合的关系大家可以参考 UML图，我在这里给出它的一种程序表现形式。package TreeIterator;public class Hall {    Tree[] tree; // 这里可以看作是聚合关系    private int index; // 指向Tree[]的标签    public Hall(int maxNumber) {        tree = new Tree[maxNumber];        index = 0;    }    public void add(Tree tree) {        this.tree[index] = tree;        index++;    }    public Iterator connectIterator() {        return new TreeIterator(this);    }} 这里我们定义的山可以抽象出Hall类来， Tree[] tree可以看作是山和树之间的一种聚合关系。 add方法就是添加树。问题来了，山和树有了关系，那么山和迭代器有什么关系呢。它们之间肯定有一种关系。我们有了这个容器（山），就要把这个容器来实现迭代的方法： hasNext()和 Next().恩这里我们可以看出，山和迭代器之间也是一种关联关系。我们就把它看成是一种聚合关系（TIP：聚合关系一种特殊的关联关系）。我们可以通过一个 connectIterator方法来链接山和迭代器，接下来我们要去做一个具体的迭代类，这个具体的类中间有了 hasNext()和 Next()的具体实现方法 package TreeIterator;public class TreeIterator implements Iterator {    private int last = 0;    private Hall hall;    public TreeIterator(Hall hall) {        this.hall = hall;    }    public boolean hasNext() {        if (last < hall.tree.length) return true;        else return false;    }    public Tree next() {        Tree t = hall.tree[last];        last++;        return t;    }}  这里Hall hall就可以看作是一种关联关系，我们要把山和迭代器联系起来就通过构造函数来实现， hasNext和 next实现方法就体现出来了有了山，有了迭代器，可是树还没有定义，不过这个树的方法还很好解决！树不关联其他的事务，我们可以简单的这么写： package TreeIterator;public class Tree {    private String name;    public Tree(String name) {        this.name = name;    }    public String getName() {