二叉树、栈、队列、链表

这些源代码,来自大三安卓培训的一次考试,主要由我的同学编写,代码由经过一定调整。

二叉树链表

前序遍历:先访问根节点,然后访问左子树、右子树
中序遍历:先访问左子树,然后访问根节点、右子树
后序遍历:先访问左子树、右子树,然后访问根节点

二叉树

/**
 * 二叉树
 * 
 * @author ChenSS 2016/11/10
 * @version 1.0
 */
public class BinaryTree {
    // 根节点数据
    int data; 
    // 左子树
    BinaryTree left; 
    // 右子树
    BinaryTree right; 

    public BinaryTree(int data) {
        this.data = data;
        left = null;
        right = null;
    }

    /**
     * 插入新的节点,以根节点为准,大的放右边,小的放左边
     * 
     * @param root
     *            根节点
     * @param data
     *            数据
     */
    public void insert(BinaryTree root, int data) {
        if (data > root.data) {
            if (root.right == null) {
                root.right = new BinaryTree(data);
            } else {
                this.insert(root.right, data);
            }
        } else {
            if (root.left == null) {
                root.left = new BinaryTree(data);
            } else {
                this.insert(root.left, data);
            }
        }
    }
}

二叉树遍历:

/**
 * 二叉树遍历
 * 
 * @author ChenSS 2016/11/10
 * @version 1.0
 */
public class BinaryTreePreorder {
    /**
     * 先根遍历,优先输出根节点的值,然后遍历左子树,左子树为空,就遍历右子树
     * 假设左子树不为空,输出左子树的根节点,继续对左子树的左右子树相同判断
     */
    public static void preOrder(BinaryTree root) {
        if (root == null)
            return;
        System.out.print(root.data + "-");
        preOrder(root.left);
        preOrder(root.right);
    }

    /**
     * 中根遍历
     */
    public static void inOrder(BinaryTree root) {
        if (root == null)
            return;
        inOrder(root.left);
        System.out.print(root.data + "-");
        inOrder(root.right);
    }

    /**
     * 后根遍历
     */
    public static void postOrder(BinaryTree root) {
        if (root == null)
            return;
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.data + "-");
    }

    public static void main(String[] str) {
        int[] array = { 12, 76, 35, 22, 16, 48, 90, 46, 9, 40 };
        BinaryTree root = new BinaryTree(array[0]);
        for (int i = 1; i < array.length; i++) {
            root.insert(root, array[i]); // 向二叉树中插入数据
        }
        System.out.println("先根遍历:");
        preOrder(root);
        System.out.println();
        System.out.println("中根遍历:");
        inOrder(root);
        System.out.println();
        System.out.println("后根遍历:");
        postOrder(root);
    }
}

这里写图片描述

生成的二叉树如上,先序遍历的输出情况为:
12-9-76-35-22-16-48-46-40-90
如图:
1. 第一个根节点是12,打印12.
2. 12有左子树和右子树,先遍历左子树,左子树根节点是9,打印9.
3. 9没有子树,所以会去判断12的右子树,右子树的根节点是76,打印76.
4. 76左右子树都有,先遍历左子树,左子树的根节点是35,打印35.
打印22……
打印16……
5. 35的左子树遍历完了,遍历右子树,打印48……

栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表,是一种后进先出(LILO)的线性表。
这里写图片描述

栈的链表实现

/**
 * 链表栈
 * 
 * @author ChenSS 2016/11/10
 * @version 1.0
 */
public class LinkedStack implements AbsStack {
    private int count;
    private Node top;

    @Override
    public void push(Object element) {
        Node node = new Node(element);
        node.setNext(top);
        top = node;
        count++;
    }

    @Override
    public Object pop() {
        if (isEmpty())
            throw new NullPointerException("stack is null");
        Object result = top.getElement();
        top = top.getNext();
        count--;
        return result;
    }

    @Override
    public boolean isEmpty() {
        return size() == 0;
    }

    @Override
    public int size() {
        return count;
    }

    @Override
    public Object peek() {
        Object result = top.getElement();
        return result;
    }

    /**
     * 链表,每一个对象拥有下一个对象的引用
     * 
     * @author ChenSS
     *
     */
    private class Node {
        // 链表元素
        private Object element;
        // 指向下一个元素的指针(引用)
        private Node next;

        public Node(Object element) {
            this.element = element;
        }

        public void setNext(Node top) {
            this.next = top;
        }

        public Node getNext() {
            return next;
        }

        public Object getElement() {
            return element;
        }
    }

    public static void main(String[] args) {
        LinkedStack stack = new LinkedStack();
        // 压栈10次
        for (int i = 0; i < 10; i++) {
            stack.push(i);
        }
        // 出栈5次
        System.out.println("连续执行5次出栈操作");
        for (int i = 0; i < 5; i++) {
            System.out.println(stack.pop());
        }
        System.out.println("栈是否为空: " + stack.isEmpty());
        System.out.println("栈的大小为: " + stack.size());
        System.out.println("栈顶元素为: " + stack.peek());
    }
}

栈的数组实现

/**
 * 数组栈
 * 
 * @author ChenSS 2016/11/10
 * @version 1.0
 */
public class ArrayStack implements AbsStack {
    // 初始化一部分空间
    private Object[] objs = new Object[16];
    private int size = 0;

    public void clear() {
        for (int i = 0; i < size; i++)
            objs[size] = null;
        size = 0;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("ArrayStack: [");
        for (int i = 0; i < size; i++) {
            sb.append(objs[i].toString());
            if (i != size - 1) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    @Override
    public void push(Object element) {
        if (size >= objs.length) {
            resize();
        }
        objs[size++] = element;
    }

    @Override
    public Object pop() {
        if (size == 0) {
            return null;
        }
        return objs[--size];
    }

    @Override
    public Object peek() {
        return objs[size];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public int size() {
        return size;
    }

    /**
     * 数组扩容,一次加5个
     */
    private void resize() {
        objs = Arrays.copyOf(objs, objs.length + 5);
    }

    public static void main(String[] args) {
        ArrayStack stack = new ArrayStack();
        // 压栈10次
        for (int i = 0; i < 10; i++) {
            stack.push(i);
        }
        // 出栈5次
        System.out.println("连续执行5次出栈操作");
        for (int i = 0; i < 5; i++) {
            System.out.println(stack.pop());
        }
        System.out.println("栈是否为空: " + stack.isEmpty());
        System.out.println("栈的大小为: " + stack.size());
        System.out.println("栈顶元素为: " + stack.peek());
        System.out.println("元素为: " + stack.toString());
    }
}

队列

队尾入列队头出,采用的是一种先进先出(LILO)的方式进行数据处理
这里写图片描述

/**
 * 队列
 * 
 * @author ChenSS 2016/11/10
 * @version 1.0
 */
public class Queue {
    // 队列长度,由构造函数初始化
    private int maxSize;
    // 队列
    private long[] queArray;
    // 队头
    private int front;
    // 队尾
    private int rear;
    // 元素的个数
    private int size;

    public Queue(int s) {
        maxSize = s;
        queArray = new long[maxSize];
        front = 0;
        rear = -1;
        size = 0;
    }

    // 进队列
    public void add(long j) {
        // 处理循环
        if (rear == maxSize - 1)
            rear = -1;
        // 队尾指针加1,把值j加入队尾
        queArray[++rear] = j;
        size++;
    }

    // 取得队列的队头元素。
    public long take() {
        // 取值和修改队头指针
        long temp = queArray[front++];
        // 处理循环
        if (front == maxSize)
            front = 0;
        size--;
        return temp;
    }

    // 取得队列的队头元素。该运算与 remove()不同,后者要修改队头元素指针。
    public long peek() {
        return queArray[front];
    }

    public boolean isEmpty() {
        return (size == 0);
    }

    // 判队列是否已满。若已满返回一个真值,否则返回一个假值。
    public boolean isFull() {
        return (size == maxSize);
    }

    // 返回队列的长度
    public int size() {
        return size;
    }

    public static void main(String[] args) {
        // 队列有5个元素
        Queue theQueue = new Queue(5);

        // 添加4个元素
        theQueue.add(10);
        theQueue.add(20);
        theQueue.add(30);
        theQueue.add(40);

        // 移除3个元素
        theQueue.take();
        theQueue.take();
        theQueue.take();

        // 添加4个元素
        theQueue.add(50);
        theQueue.add(60);
        theQueue.add(70);
        theQueue.add(80);

        // 遍历队列并移除所有元素
        while (!theQueue.isEmpty()) {
            long n = theQueue.take();
            System.out.print(n);
            System.out.print(" ");
        }
    }
}

链表

单向链表

在表头插入一个新的链接点,每个元素有下一个元素的指针(索引),根据当前元素,可以获取下一个元素。
这里写图片描述

双端链表

与单向链表的不同之处在保存有对最后一个链接点的引用(last),实现了在链尾也可以插入数据的功能
这里写图片描述

双向链表

在过去的学习中,我们使用到了迭代器,迭代器有个向后遍历的功能,而双向链表,就增加了一个功能:往回遍历。每一个元素有两个指针,一个指向前一个元素,一个指向后一个元素。(参考:LinkedList对象)
这里写图片描述

LinkedList底层代码(LinkedList的元素):
每一个元素包含两个指针(引用),一个指向前面一个元素,一个指向后面一个元素,也就是说,我们只要能得到其中任何一个元素,就可以遍历整个链表。

   private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

LinkedList逆向遍历功能展示:

/**
 * LinkedList测试
 * 
 * @author ChenSS 2016/11/10
 * @version 1.0
 */
public class BinaryTreePlus {
    public static void main(String[] args) {
        LinkedList<String> list=new LinkedList<>();
        list.addFirst("AAA");
        list.addLast("BBB");
        ListIterator<String> iterator=list.listIterator(list.size());
        while(iterator.hasPrevious()){
            System.out.println(iterator.previous());
        }
    }
}

LinkedList代码实现:

/**
 * 双向链表
 * 
 * @author ChenSS 2016/11/10
 * @version 1.0
 */
public class DoubleLists<T> {
    private DNode<T> header; 
    private int listSize;

    public DoubleLists() {
        header = new DNode<T>();
        listSize = 0;
    }
    private static class DNode<T> {
        T nodeValue;
        DNode<T> prev;
        DNode<T> next;

        public DNode() { // for header
            nodeValue = null;
            prev = this; // left
            next = this; // right
        }

        public DNode(T item) {
            nodeValue = item;
            prev = this;
            next = this;
        }
    }

    public boolean isEmpty() {
        return (header.prev == header || header.next == header);
    }

    public int size() {
        return listSize;
    }

    private DNode<T> addBefore(DNode<T> curr, T item) {
        DNode<T> newNode, prevNode;

        newNode = new DNode<T>(item);

        prevNode = curr.prev;

        newNode.prev = prevNode;
        newNode.next = curr;

        prevNode.next = newNode;
        curr.prev = newNode;

        return newNode;
    }

    public boolean add(T item) {
        addBefore(header, item);
        listSize++;
        return true;
    }

    public void addFirst(T item) {
        addBefore(header.next, item);
        listSize++;
    }

    public void addLast(T item) {
        addBefore(header, item);
        listSize++;
    }

    private void remove(DNode<T> curr) {
        if (curr.next == curr)
            return;

        DNode<T> prevNode = curr.prev, nextNode = curr.next;

        prevNode.next = nextNode;
        nextNode.prev = prevNode;
    }

    public boolean remove(Object o) {
        for (DNode<T> p = header.next; p != header; p = p.next) {
            if (o.equals(p.nodeValue)) {
                remove(p);
                listSize--;
                return true;
            }
        }
        return false;
    }

    public void printList() {
        for (DNode<T> p = header.next; p != header; p = p.next)
            System.out.println(p.nodeValue);
    }

    private class MyIterator implements Iterator<T> {

        public DNode<T> nextNode = header.next;
        public DNode<T> lastReturned = header;

        public boolean hasNext() {
            return nextNode != header;
        }

        public T next() {
            if (nextNode == header)
                throw new NoSuchElementException("");

            lastReturned = nextNode;
            nextNode = nextNode.next;
            return lastReturned.nodeValue;
        }

        public void remove() {
            if (lastReturned == header)
                throw new IllegalStateException("");

            DoubleLists.this.remove(lastReturned);
            lastReturned = header;
            listSize--;
        }
    }

    private class MyListIterator extends MyIterator implements ListIterator<T> {

        private int nextIndex;

        MyListIterator(int index) {
            if (index < 0 || index > listSize)
                throw new IndexOutOfBoundsException("");
            if (index < (listSize >> 1)) {
                nextNode = header.next;
                for (nextIndex = 0; nextIndex < index; nextIndex++)
                    nextNode = nextNode.next;
            } else {
                nextNode = header;
                for (nextIndex = listSize; nextIndex > index; nextIndex--)
                    nextNode = nextNode.prev;
            }
        }

        public boolean hasPrevious() {
            return nextIndex != 0;
            // return nextNode.prev != header;
        }

        public T previous() {
            if (nextIndex == 0)
                throw new NoSuchElementException("no");

            lastReturned = nextNode = nextNode.prev;
            nextIndex--;
            return lastReturned.nodeValue;
        }

        public void remove() {
            if (lastReturned == header)
                throw new IllegalStateException("");

            DoubleLists.this.remove(lastReturned);
            nextIndex--;
            listSize--;

            if (lastReturned == nextNode)
                nextNode = nextNode.next;
            lastReturned = header;
        }

        public void add(T item) {
            DoubleLists.this.addBefore(nextNode, item);
            nextIndex++;
            listSize++;
            lastReturned = header;
        }

        public void set(T item) {
            if (lastReturned == header)
                throw new IllegalStateException();

            lastReturned.nodeValue = item;
        }

        public int nextIndex() {
            return nextIndex;
        }

        public int previousIndex() {
            return nextIndex - 1;
        }
    }

    public Iterator<T> iterator() {
        return new MyIterator();
    }

    public ListIterator<T> listIterator(int index) {
        return new MyListIterator(index);
    }

    public static void main(String[] args) {
        DoubleLists<String> t = new DoubleLists<String>();
        t.add("A");
        t.add("B");
        t.remove("B");
        t.addFirst("AA");
        t.addLast("BB");
        t.add("C");
        t.add("D");

        ListIterator<String> it = t.listIterator(t.size());

        while (it.hasPrevious()) {
            //指向位置前面的元素
            System.out.println(it.previous()); 
        }
    }
}

4种常见的排序

/**
 * 排序算法
 * 
 * @author ChenSS 2016/11/10
 * @version 1.0
 */
public class SortUtil {
    /**
     * 选择排序,采用记角标的方式,记住数组中最小的那个数的角标,然后与开始的元素交换位置
     */
    public static void selectSort(int[] a) {
        int index;
        int temp;
        for (int i = 0; i < a.length - 1; i++) {
            index = i;
            for (int j = i + 1; j < a.length; j++) {
                if (a[index] > a[j])
                    index = j;
            }
            if (index != i) {
                temp = a[index];
                a[index] = a[i];
                a[i] = temp;
            }
        }

    }

    /**
     * 快速排序,以一个数为基准(通常选第一个数),大数置于右边,小数置于左边,
     * 此后以相同的算法对左边和右边这两组数进行排序,以此类推,
     * 直至整个数组从小到大排列
     */
    public static void quickSort(int[] a, int left, int right) {
        if (left >= right)
            return;
        int temp = a[left];
        int low = left;
        int high = right;
        while (low < high) {
            while (low < high && a[high] >= temp)
                high--;
            a[low] = a[high];
            while (low < high && a[low] <= temp)
                low++;
            a[high] = a[low];
        }
        a[low] = temp;
        quickSort(a, left, low - 1);
        quickSort(a, low + 1, right);
    }

    /**
     * 冒泡排序
     */
    public static void bubbleSort(int[] a) {
        int temp;
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a.length - i - 1; j++) {
                if (a[j] > a[j + 1]) {
                    temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }
            }
        }
    }

    /**
     * 插入排序,和选择排序类似,遍历取出最小的那个数,然后插入到第一个元素的位置,其它元素全部后移
     */
    public static void insertSort(int a[]) {
        for (int i = 1; i < a.length; i++) {
            int key = a[i];
            int index = i;
            while (index > 0 && a[index - 1] > key) {
                a[index] = a[index - 1];
                index--;
            }
            a[index] = key;
        }
    }

    /**
     * 测试方法
     */
    public static void print(int a[]) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int[] arr = { 7, 6, 5, 4, 2, 3, 9, 90, 4, 50 };
        insertSort(arr);
        print(arr);
    }
}

posted on 2016-11-16 11:24  疯狂的妞妞  阅读(406)  评论(0编辑  收藏  举报

导航