头歌JAVA数据结构答案

头歌JAVA数据结构答案

一、Java数据结构-循环链表的设计与实现

第1关 单循环链表的实现—链表的添加、遍历

package step1;
/**
 * Created by sykus on 2018/1/15.
 */
public class MyCircleLinkedList {
    private Node head;//头结点, 不存数据
    private Node tail;//尾结点, 指向链表的最后一个节点
    private int size;
    public MyCircleLinkedList() {
        head = new Node(Integer.MIN_VALUE, null);
        head.next = head;
        tail = head;
        size = 0;
    }
    /**
     * 添加到链表尾部
     *
     * @param item
     */
    public void add(int item) {
        /********** Begin *********/
        Node node = new Node(item, tail.next);
        tail.next = node;
        tail = node;
        ++size;
        /********** End *********/
    }
    /**
     * 遍历链表并输出元素
     */
    public void output() {
        /********** Begin *********/
        Node p = head;
        while (p.next != head) {
            p = p.next;
            System.out.println(p.item);
        }
        /********** End *********/
    }
    public boolean isEmpty() {
        return head.next == head;
    }
    public int size() {
        return size;
    }
    //结点内部类
    private static class Node {
        int item;
        Node next;
        Node(int item, Node next) {
            this.item = item;
            this.next = next;
        }
    }
}

第2关 单循环链表的实现—链表的删除

package step2;
/**
 * Created by sykus on 2018/1/15.
 */
public class MyCircleLinkedList {
    private Node head;//头结点, 不存数据
    private Node tail;//尾结点, 指向链表的最后一个节点
    private int size;
    public MyCircleLinkedList() {
        head = new Node(Integer.MIN_VALUE, null);
        head.next = head;
        tail = head;
        size = 0;
    }
    /**
     * 添加到链表尾部
     *
     * @param item
     */
    public void add(int item) {
        Node node = new Node(item, tail.next);
        tail.next = node;
        tail = node;
        ++size;
    }
    /**
     * 遍历链表并输出元素
     */
    public void output() {
        Node p = head;
        while (p.next != head) {
            p = p.next;
            System.out.println(p.item);
        }
    }
    /**
     * 删除从头结点开始的第index个结点
     * index从0开始
     *
     * @param index
     * @return
     */
    public int remove(int index) {
        checkPosIndex(index);
        /********** Begin *********/
        Node f = head;
        while ((index--) > 0) {
            f = f.next;
        }
        Node del = f.next;
        if (del == tail) {//要删除的是尾结点
            tail = f;//使tail依然指向末尾结点
        }
        f.next = del.next;
        del.next = null;
        int oldVal = del.item;
        del = null;
        --size;
        return oldVal;
        /********** End *********/
    }
    public boolean isEmpty() {
        return head.next == head;
    }
    public int size() {
        return size;
    }
    private void checkPosIndex(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
    }
    //结点内部类
    private static class Node {
        int item;
        Node next;
        Node(int item, Node next) {
            this.item = item;
            this.next = next;
        }
    }
}

第3关 双向循环链表的实现—链表的插入

package step3;
/**
 * Created by sykus on 2018/1/15.
 */
public class MyDoubleLinkedList {
    private Node head;//头结点
    private Node tail;//指向链表的尾结点
    private int size;
    public MyDoubleLinkedList() {
        head = new Node(null, Integer.MIN_VALUE, null);
        head.next = head.prev = head;
        tail = head;
        size = 0;
    }
    /**
     * 添加元素到表尾
     *
     * @param item
     */
    public void add(int item) {
        /********** Begin *********/
        Node newNode = new Node(null, item, null);
        tail.next = newNode;
        newNode.prev = tail;
        newNode.next = head;
        head.prev = newNode;
        tail = newNode;
        ++size;
        /********** End *********/
    }
    /**
     * 打印双向链表
     *
     * @param flag true从左向右顺序打印, false从右向左顺序打印
     */
    public void printList(boolean flag) {
        Node f = head;
        if (flag) {//向右
            while (f.next != head) {
                f = f.next;
                System.out.print(f.item + " ");
            }
        } else {//向左
            while (f.prev != head) {
                f = f.prev;
                System.out.print(f.item + " ");
            }
        }
    }
    public int size() {
        return size;
    }
    //结点内部类
    private static class Node {
        int item;
        Node next;//直接后继引用
        Node prev;//直接前驱引用
        Node(Node prev, int item, Node next) {
            this.prev = prev;
            this.item = item;
            this.next = next;
        }
    }
}

第4关:双向循环链表的实现—链表的删除

package step4;
/**
 * Created by sykus on 2018/1/15.
 */
public class MyDoubleLinkedList {
    private Node head;//头结点
    private Node tail;//指向链表的尾结点
    private int size;
    public MyDoubleLinkedList() {
        head = new Node(null, Integer.MIN_VALUE, null);
        head.next = head.prev = head;
        tail = head;
        size = 0;
    }
    /**
     * 添加元素到表尾
     *
     * @param item
     */
    public void add(int item) {
        Node newNode = new Node(null, item, null);
        tail.next = newNode;
        newNode.prev = tail;
        newNode.next = head;
        head.prev = newNode;
        tail = newNode;
        ++size;
    }
    /**
     * 删除指定位置index出的结点,并返回其值
     *
     * @param index
     * @return
     */
    public int remove(int index) {
        checkPosIndex(index);//
        /********** Begin *********/
        Node p = head.next;
        while ((index--) > 0) {
            p = p.next;
        }
        if (p == tail) {
            tail = p.prev;
        }
        p.prev.next = p.next;
        p.next.prev = p.prev;
        int val = p.item;
        p = null;
        --size;
        return val;
        /********** End *********/
    }
    /**
     * 打印双向链表
     *
     * @param flag true从左向右顺序打印, false从右向左顺序打印
     */
    public void printList(boolean flag) {
        Node f = head;
        if (flag) {//向右
            while (f.next != head) {
                f = f.next;
                System.out.print(f.item + " ");
            }
        } else {//向左
            while (f.prev != head) {
                f = f.prev;
                System.out.print(f.item + " ");
            }
        }
    }
    public int size() {
        return size;
    }
    private void checkPosIndex(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
    }
    //结点内部类
    private static class Node {
        int item;
        Node next;//直接后继引用
        Node prev;//直接前驱引用
        Node(Node prev, int item, Node next) {
            this.prev = prev;
            this.item = item;
            this.next = next;
        }
    }
}

二、Java数据结构-线性表的设计与实现

第1关:顺序表的实现之增删功能

package step1;
/**
 * Created by zengpeng on 2017/12/25.
 */
public class MyArrayList {
    private int[] elements;//元素
    private int size;//List中当前的元素个数
    public MyArrayList() {
        this(1);//List默认大小为1
    }
    /**
     * 按指定大小capacity构造List
     *
     * @param capacity List初始化时的大小
     */
    public MyArrayList(int capacity) {
        elements = new int[capacity];
        size = 0;
    }
    /**
     * 返回List中元素的个数
     *
     * @return
     */
    public int size() {
        return size;
    }
    /**
     * 添加一个元素到末尾
     *
     * @param item
     */
    public void Add(int item) {
        int len = elements.length;
        if (size == len - 1) {
            resize(2 * len);
        }
        /********** Begin *********/
        elements[size++] = item;
        /********** End *********/
    }
    /**
     * 添加一个元素到指定位置index
     *
     * @param index
     * @param item
     */
    public void Add(int index, int item) {
        validateRangeForAdd(index);
        int len = elements.length;
        if (size == len - 1) {
            resize(2 * len);
        }
        /********** Begin *********/
        for (int i = size; i > index; i--) {
            elements[i] = elements[i - 1];
        }
        elements[index] = item;
        size++;
        /********** End *********/
    }
    /**
     * 删除指定位置index的元素,并返回被删除的元素
     *
     * @param index
     * @return
     */
    public int remove(int index) {
        validateRange(index);
        /********** Begin *********/
        int oldVal=elements[index];
        for (int i = index; i < size - 1; i++) {
            elements[i] = elements[i + 1];
        }
        --size;
        return oldVal;
        /********** End *********/
    }
    /**
     * 校验索引范围
     *
     * @param index
     */
    private void validateRange(int index) {
        if (index >= size || index < 0) {
            throw new ArrayIndexOutOfBoundsException("索引越界了哦!Index: " + index + ", Size: " + size);
        }
    }
    /**
     * 校验索引范围
     *
     * @param index
     */
    private void validateRangeForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException("索引越界了哦!Index: " + index + ", Size: " + size);
    }
    /**
     * 动态扩展数组大小
     *
     * @param capacity
     */
    private void resize(int capacity) {
        assert capacity > size;
        int[] tmp = new int[capacity];
        for (int i = 0; i < size; i++) {
            tmp[i] = elements[i];
        }
        elements = tmp;
    }
}

第2关: 顺序表的实现之查询功能

package step2;
/**
 * Created by zengpeng on 2017/12/25.
 */
public class MyArrayList {
    private int[] elements;//元素
    private int size;//List中当前的元素个数
    public MyArrayList() {
        this(1);//List默认大小为1
    }
    /**
     * 按指定大小capacity构造List
     *
     * @param capacity List初始化时的大小
     */
    public MyArrayList(int capacity) {
        elements = new int[capacity];
        size = 0;
    }
    /**
     * 返回List中元素的个数
     *
     * @return
     */
    public int size() {
        return size;
    }
    /**
     * 添加一个元素到末尾
     *
     * @param item
     */
    public void Add(int item) {
        int len = elements.length;
        if (size == len - 1) {
            resize(2 * len);
        }
        elements[size++] = item;
    }
    /**
     * 添加一个元素到指定位置index
     *
     * @param index
     * @param item
     */
    public void Add(int index, int item) {
        validateRangeForAdd(index);
        int len = elements.length;
        if (size == len - 1) {
            resize(2 * len);
        }
        for (int i = size; i > index; i--) {
            elements[i] = elements[i - 1];
        }
        elements[index] = item;
        size++;
    }
    /**
     * 删除指定位置index的元素,并返回被删除的元素
     *
     * @param index
     * @return 被删除的元素
     */
    public int remove(int index) {
        validateRange(index);
        int oldVal = elements[index];
        for (int i = index; i < size - 1; i++) {
            elements[i] = elements[i + 1];
        }
        --size;
        return oldVal;
    }
    /**
     * 返回表中下标为index的元素
     * @param index 下标
     * @return
     */
    public int get(int index) {
        validateRange(index);
        /********** Begin *********/
        return elements[index];
        /********** End *********/
    }
    /**
     * 校验索引范围
     *
     * @param index
     */
    private void validateRange(int index) {
        if (index >= size || index < 0) {
            throw new ArrayIndexOutOfBoundsException("索引越界了哦!Index: " + index + ", Size: " + size);
        }
    }
    /**
     * 校验索引范围
     *
     * @param index
     */
    private void validateRangeForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException("索引越界了哦!Index: " + index + ", Size: " + size);
    }
    /**
     * 动态扩展数组大小
     *
     * @param capacity
     */
    private void resize(int capacity) {
        assert capacity > size;
        int[] tmp = new int[capacity];
        for (int i = 0; i < size; i++) {
            tmp[i] = elements[i];
        }
        elements = tmp;
    }
}

第3关:单链表的实现之增删功能

package step3;
/**
 * Created by zengpeng on 2017/12/25.
 */
public class MyLinkedList {
    private Node first;//头结点,不存数据
    private Node last;//指向链表的最后一个节点
    private int size;
    public MyLinkedList() {
        size = 0;
        first = new Node(0, null);
        last = null;
    }
    /**
     * 添加到链表尾部
     *
     * @param item
     */
    public void add(int item) {
        /********** Begin *********/
        final Node l = last;
        final Node node = new Node(item, null);
        last = node;
        if (first.next == null) {//首次添加
            first.next = node;
        } else {
            l.next = node;
        }
        ++size;
        /********** End *********/
    }
    /**
     * 添加数据item到指定位置index
     * index从0开始
     * @param index
     * @param item
     */
    public void add(int index, int item) {
        checkPosIndex(index);
        /********** Begin *********/
        int n = index;
        Node l = first;
        while ((n--) > 0) {
            l = l.next;
        }
        final Node node = new Node(item, null);
        if (null == first.next) {//首次添加
            last = node;
        }
        node.next = l.next;
        l.next = node;
        ++size;
        /********** End *********/
    }
    /**
     * 删除指定位置index处的元素并返回, index从0开始
     * @param index
     * @return
     */
    public int remove(int index) {
        checkPosIndex(index);
        /********** Begin *********/
        Node f = first;
        while ((index--) > 0) {
            f = f.next;
        }
        Node del = f.next;
        if (del == last) {//删除最后一个元素
            last = f;
        }
        f.next = del.next;
        del.next = null;
        int oldVal = del.item;
        del = null;
        --size;
        return oldVal;
        /********** End *********/
    }
    public int size() {
        return size;
    }
    private void checkPosIndex(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
    }
    //结点内部类
    private static class Node {
        int item;
        Node next;
        Node(int item, Node next) {
            this.item = item;
            this.next = next;
        }
    }
}

第4关:单链表的实现之查询功能

package step4;
/**
 * Created by zengpeng on 2017/12/25.
 */
public class MyLinkedList {
    private Node first;//头结点,不存数据
    private Node last;//指向链表的最后一个节点
    private int size;
    public MyLinkedList() {
        size = 0;
        first = new Node(0, null);
        last = null;
    }
    /**
     * 添加到链表尾部
     *
     * @param item
     */
    public void add(int item) {
        final Node l = last;
        final Node node = new Node(item, null);
        last = node;
        if (first.next == null) {//首次添加
            first.next = node;
        } else {
            l.next = node;
        }
        ++size;
    }
    /**
     * 添加数据item到指定位置index
     * index从0开始
     * @param index
     * @param item
     */
    public void add(int index, int item) {
        checkPosIndex(index);
        int n = index;
        Node l = first;
        while ((n--) > 0) {
            l = l.next;
        }
        final Node node = new Node(item, null);
        if (null == first.next) {//首次添加
            last = node;
        }
        node.next = l.next;
        l.next = node;
        ++size;
    }
    /**
     * 删除指定位置index处的元素并返回, index从0开始
     * @param index
     * @return
     */
    public int remove(int index) {
        checkPosIndex(index);
        Node f = first;
        while ((index--) > 0) {
            f = f.next;
        }
        Node del = f.next;
        if (del == last) {//删除最后一个元素
            last = f;
        }
        f.next = del.next;
        del.next = null;
        int oldVal = del.item;
        del = null;
        --size;
        return oldVal;
    }
    /**
     * 获取链表中第index个元素
     * @param index
     * @return
     */
    public int get(int index) {
        checkPosIndex(index);
        /********** Begin *********/
        Node f = first.next;
        while ((index--) > 0) {
            f = f.next;
        }
        int val = f.item;
        return val;
        /********** End *********/
    }
    public int size() {
        return size;
    }
    private void checkPosIndex(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
        }
    }
    //结点内部类
    private static class Node {
        int item;
        Node next;
        Node(int item, Node next) {
            this.item = item;
            this.next = next;
        }
    }
    }

三、Java 数据结构之栈、队列

第1关:实现基于数组的栈

package step1;
import java.util.NoSuchElementException;
/**
 * Created by sykus on 2018/1/26.
 */
public class MyStack<T> {
    private T[] S;
    private int top;//栈顶元素下标,初始为-1
    public MyStack() {
        this(1);
    }
    public MyStack(int capacity) {
        S = (T[]) new Object[capacity];
        top = -1;
    }
    /**
     * 入栈操作,把item压入栈中
     *
     * @param item
     */
    public void push(T item) {
        int len = S.length;
        if (top == len - 1) {
            resize(2 * len);
        }
        /********** Begin *********/
        S[++top] = item;
        /********** End *********/
    }
    /**
     * 返回栈顶元素并从栈中移除
     *
     * @return
     */
    public T pop() {
        if (isEmpty()) {
            throw new NoSuchElementException("栈为空!");
        }
        /********** Begin *********/
        T val = S[top--];
        return val;
        /********** End *********/
    }
    /**
     * 判断栈是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        if (top < 0)
            return true;
        else
            return false;
    }
    /**
     * 动态扩展数组大小
     *
     * @param capacity
     */
    private void resize(int capacity) {
        assert capacity > top;
        T[] tmp = (T[]) new Object[capacity];
        for (int i = 0; i <= top; i++) {
            tmp[i] = S[i];
        }
        S = tmp;
    }
}

第2关:实现基于链表的栈

package step2;
import java.util.NoSuchElementException;
/**
 * Created by sykus on 2017/12/29.
 */
public class MyStack<E> {
    private Node<E> head;//头结点
    private Node<E> top;//栈顶
    private int size;//栈中元素个数
    public MyStack() {
        head = new Node<E>();
        head.next = null;
        top = null;//栈顶初始化为null
        size = 0;
    }
    /**
     * 把item压入栈中
     *
     * @param item
     */
    public void push(E item) {
        /********** Begin *********/
        Node<E> newNode = new Node<E>();
        newNode.item = item;
        newNode.next = head.next;
        head.next = newNode;
        top = newNode;
        ++size;
        /********** End *********/
    }
    /**
     * 返回它栈顶元素并删除
     */
    public E pop() {
        if (isEmpty())
            throw new NoSuchElementException("栈为空!");
        /********** Begin *********/
        Node<E> node = top;
        top = top.next;
        head.next = top;
        node.next = null;
        --size;
        return node.item;
        /********** End *********/
    }
    /**
     * 返回栈中元素个数
     *
     * @return
     */
    public int size() {
        return size;
    }
    /**
     * 判断一个栈是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return (null == head);
    }
    //链表结点内部类
    private static class Node<E> {
        private E item;
        private Node<E> next;
    }
}

第3关:基于数组的队列

package step3;
/**
 * Created by zengpeng on 2018/1/30.
 */
public class MyQueue<T> {
    private T[] Q;
    private int head;
    private int tail;
    private int size;
    public MyQueue() {
        this(1);
    }
    public MyQueue(int capacity) {
        Q = (T[]) new Object[capacity];
        size = 0;
        head = tail = 0;
    }
    /**
     * 入队操作
     *
     * @param item
     */
    public void enqueue(T item) {
        /********** Begin *********/
        Q[tail] = item;
        tail = (tail + 1) % Q.length;
        ++size;
        /********** End *********/
    }
    /**
     * 出队操作
     *
     * @return
     */
    public T dequeue() {
        /********** Begin *********/
        T val = Q[head];
        head = (head + 1) % Q.length;
        --size;
        return val;
        /********** End *********/
    }
    /**
     * 判断队列是否为空
     * @return
     */
    public boolean isEmpty() {
        return (head == tail) && (size < Q.length);
    }
    public int size() {
        return size;
    }
}

第4关:基于链表的队列

package step4;
import java.util.NoSuchElementException;
/**
 * Created by sykus on 2017/12/29.
 */
public class MyQueue<T> {
    private Node<T> head;// 头结点,不存数据
    private Node<T> front;//指向队头结点
    private Node<T> tail;//指向队尾结点
    private int size;
    public MyQueue() {
        head = new Node<T>();
        front = tail = null;
        size = 0;
    }
    /**
     * 入队
     *
     * @param item
     */
    public void enqueue(T item) {
        /********** Begin *********/
        Node<T> oldTail = tail;
        Node<T> newNode = new Node<T>();
        newNode.item = item;
        newNode.next = null;
        if (null == front) {//空队列
            head.next = newNode;
            front = newNode;
        } else {
            oldTail.next = newNode;
        }
        tail = newNode;
        ++size;
        /********** End *********/
    }
    /**
     * 出队
     *
     * @return
     */
    public T dequeue() {
        if (isEmpty())
            throw new NoSuchElementException("队列为空!");
        /********** Begin *********/
        T val = front.item;
        head.next = front.next;
        front.next = null;
        front = head.next;//此时队头为后继结点
        --size;
        if (null == head.next) {//出队的是队列中的最后一个元素
            front = tail = null;
        }
        return val;
        /********** End *********/
    }
    /**
     * 返回队列中元素数量
     *
     * @return
     */
    public int size() {
        return size;
    }
    /**
     * 判断一个队列是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return (front == null);
    }
    /**
     * 链表结点内部类
     */
    private static class Node<E> {
        private E item;
        private Node<E> next;
    }
}

四、Java 数据结构之二叉搜索树

第1关:二叉搜索树的介绍与构建

package step1;
/**
 * Created by zengpeng on 2018/3/3.
 */
public class BSTree {
    private TreeNode root;//根结点
    public BSTree() {
        root = null;
    }
    /**
     * 向树root中插入key
     *
     * @param key 要插入的值
     */
    public void insert(int key) {
        /********** Begin *********/
        TreeNode x = root;
        TreeNode p = null;//始终指向x的父结点
        while (x != null) {
            p = x;
            if (key < x.item) {
                x = x.leftChild;
            } else {
                x = x.rightChild;
            }
        }
        if (null == p) {//空树
            root = new TreeNode(key);
        } else if (key < p.item) {
            p.leftChild = new TreeNode(key);
        } else {
            p.rightChild = new TreeNode(key);
        }
        /********** End *********/
    }
    /**
     * 前序遍历
     */
    public void preOrder() {
        preOrder(root);
    }
    /**
     * 中序遍历
     */
    public void inOrder() {
        inOrder(root);
    }
    /**
     * 后序遍历
     */
    public void postOrder(){
        postOrder(root);
    }
    private void preOrder(TreeNode node) {
        if (node != null) {
            System.out.print(node.item + " ");
            preOrder(node.leftChild);
            preOrder(node.rightChild);
        }
    }
    private void inOrder(TreeNode node) {
        if (node != null) {
            inOrder(node.leftChild);
            System.out.print(node.item + " ");
            inOrder(node.rightChild);
        }
    }
    private void postOrder(TreeNode node) {
        if (node != null) {
            postOrder(node.leftChild);
            postOrder(node.rightChild);
            System.out.print(node.item + " ");
        }
    }
    public static class TreeNode {
        private TreeNode leftChild;
        private TreeNode rightChild;
        private int item;
        public TreeNode(int item) {
            this(null, null, item);
        }
        public TreeNode(TreeNode leftChild, TreeNode rightChild, int item) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
            this.item = item;
        }
    }
}

第2关:二叉搜索树的删除

package step2;
/**
 * Created by zengpeng on 2018/3/14.
 */
public class BSTree {
    private TreeNode root;//根结点
    public BSTree() {
        root = null;
    }
    /**
     * 向树root中插入a
     *
     * @param key 要插入的值
     */
    public void insert(int key) {
        TreeNode x = root;
        TreeNode p = null;//始终指向x的父结点
        while (x != null) {
            p = x;
            if (key < x.item) {
                x = x.leftChild;
            } else {
                x = x.rightChild;
            }
        }
        if (null == p) {//空树
            root = new TreeNode(key);
        } else if (key < p.item) {
            p.leftChild = new TreeNode(key);
        } else {
            p.rightChild = new TreeNode(key);
        }
    }
    /**
     * 在树root中删除结点key
     *
     * @param key
     * @return
     */
    public void delete(int key) {
        root = delete(root, key);
    }
    private TreeNode delete(TreeNode x, int key) {
        /********** Begin *********/
        if (x == null) {
            return null;
        }
        if (key < x.item) {
            x.leftChild = delete(x.leftChild, key);
        } else if (key > x.item) {
            x.rightChild = delete(x.rightChild, key);
        } else {
            if (x.leftChild == null) return x.rightChild;
            if (x.rightChild == null) return x.leftChild;
            TreeNode t = x;
            x = min(t.rightChild);
            x.rightChild = deleteMin(t.rightChild);
            x.leftChild = t.leftChild;
        }
        return x;
        /********** End *********/
    }
    /**
     * 删除树x中的最小结点
     *
     * @param x
     * @return
     */
    private TreeNode deleteMin(TreeNode x) {
        if (x.leftChild == null) return x.rightChild;
        x.leftChild = deleteMin(x.leftChild);
        return x;
    }
    /**
     * 查找树x中的最小结点
     *
     * @param x
     * @return
     */
    private TreeNode min(TreeNode x) {
        TreeNode p = x;
        while (p.leftChild != null) {
            p = p.leftChild;
        }
        return p;
    }
    public void preOrder() {
        preOrder(root);
    }
    private void preOrder(TreeNode node) {
        if (node != null) {
            System.out.print(node.item + " ");
            preOrder(node.leftChild);
            preOrder(node.rightChild);
        }
    }
    public void inOrder() {
        inOrder(root);
    }
    private void inOrder(TreeNode node) {
        if (node != null) {
            inOrder(node.leftChild);
            System.out.print(node.item + " ");
            inOrder(node.rightChild);
        }
    }
    public void postOrder() {
        postOrder(root);
    }
    private void postOrder(TreeNode node) {
        if (node != null) {
            postOrder(node.leftChild);
            postOrder(node.rightChild);
            System.out.print(node.item + " ");
        }
    }
    public static class TreeNode {
        private TreeNode leftChild;
        private TreeNode rightChild;
        private int item;
        public TreeNode(int item) {
            this(null, null, item);
        }
        public TreeNode(TreeNode leftChild, TreeNode rightChild, int item) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
            this.item = item;
        }
    }
}

第3关:二叉搜索树的查找

package step3;
/**
 * Created by zengpeng on 2018/3/14.
 */
public class BSTree {
    private TreeNode root;//根结点
    public BSTree() {
        root = null;
    }
    /**
     * 向树root中插入a
     *
     * @param key    要插入的值
     */
    public void insert(int key) {
        TreeNode x = root;
        TreeNode p = null;//始终指向x的父结点
        while (x != null) {
            p = x;
            if (key < x.item) {
                x = x.leftChild;
            } else {
                x = x.rightChild;
            }
        }
        if (null == p) {//空树
            root = new TreeNode(key);
        } else if (key < p.item) {
            p.leftChild = new TreeNode(key);
        } else {
            p.rightChild = new TreeNode(key);
        }
    }
    /**
     * 判断树root中是否包含key,包含则返回true,不包含返回false
     *
     * @param key
     * @return
     */
    public boolean search(int key) {
        /********** Begin *********/
        TreeNode p = root;
        while (p != null && key != p.item) {
            if (key < p.item) {
                p = p.leftChild;
            } else {
                p = p.rightChild;
            }
        }
        if (p == null) {
            return false;
        } else {
            return true;
        }
        /********** End *********/
    }
    /**
     * 在树root中删除结点key
     *
     * @param key
     * @return
     */
    public void delete(int key) {
        root = delete(root, key);
    }
    private TreeNode delete(TreeNode x, int key) {
        if (x == null) {
            return null;
        }
        if (key < x.item) {
            x.leftChild = delete(x.leftChild, key);
        } else if (key > x.item) {
            x.rightChild = delete(x.rightChild, key);
        } else {
            if (x.leftChild == null) return x.rightChild;
            if (x.rightChild == null) return x.leftChild;
            TreeNode t = x;
            x = min(t.rightChild);
            x.rightChild = deleteMin(t.rightChild);
            x.leftChild = t.leftChild;
        }
        return x;
    }
    /**
     * 删除树x中的最小结点
     * @param x
     * @return
     */
    private TreeNode deleteMin(TreeNode x) {
        if (x.leftChild == null) return x.rightChild;
        x.leftChild = deleteMin(x.leftChild);
        return x;
    }
    /**
     * 查找树x中的最小结点
     *
     * @param x
     * @return
     */
    private TreeNode min(TreeNode x) {
        TreeNode p = x;
        while (p.leftChild != null) {
            p = p.leftChild;
        }
        return p;
    }
    public void preOrder() {
        preOrder(root);
    }
    public void inOrder() {
        inOrder(root);
    }
    public void postOrder() {
        postOrder(root);
    }
    private void preOrder(TreeNode node) {
        if (node != null) {
            System.out.print(node.item + " ");
            preOrder(node.leftChild);
            preOrder(node.rightChild);
        }
    }
    private void inOrder(TreeNode node) {
        if (node != null) {
            inOrder(node.leftChild);
            System.out.print(node.item + " ");
            inOrder(node.rightChild);
        }
    }
    private void postOrder(TreeNode node) {
        if (node != null) {
            postOrder(node.leftChild);
            postOrder(node.rightChild);
            System.out.print(node.item + " ");
        }
    }
    public static class TreeNode {
        private TreeNode leftChild;
        private TreeNode rightChild;
        private int item;
        public TreeNode(int item) {
            this(null, null, item);
        }
        public TreeNode(TreeNode leftChild, TreeNode rightChild, int item) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
            this.item = item;
        }
    }
}

五、Java 数据结构之二叉树
第1关:二叉树的实现之前序遍历

package step1;
/**
 * Created by zengpeng on 2018/2/9.
 */
public class BinaryTree {
    private TreeNode root;//根节点
    public BinaryTree() {
        root = null;
    }
    public void preOrder(TreeNode root) {
        /********** Begin *********/
        if (root == null) {
            return;
        }
        System.out.println(root.item);
        preOrder(root.leftChild);
        preOrder(root.rightChild);
        /********** End *********/
    }
    /**
     * 以数组arr从左至右构建二叉树
     *
     * @param arr
     * @param n
     * @return
     */
    public TreeNode createTree(int arr[]) {
        TreeNode tmp[] = new TreeNode[arr.length + 1];
        for (int k = 1; k <= arr.length; k++) {
            TreeNode node = new TreeNode(arr[k - 1]);
            tmp[k] = node;
            if (k == 1) {
                root = node;
            } else {
                int j = k / 2;
                if (k % 2 == 0) {
                    tmp[j].leftChild = node;
                } else {
                    tmp[j].rightChild = node;
                }
            }
        }
        return root;
    }
    public static class TreeNode {
        private TreeNode leftChild;
        private TreeNode rightChild;
        private int item;
        public TreeNode(int item) {
            this(null, null, item);
        }
        public TreeNode(TreeNode leftChild, TreeNode rightChild, int item) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
            this.item = item;
        }
    }
}

第2关:二叉树的实现之中序遍历

package step2;
/**
 * Created by zengpeng on 2018/2/12.
 */
public class BinaryTree {
    private TreeNode root;//根节点
    public BinaryTree() {
        root = null;
    }
    public void inOrder(TreeNode root) {
        /********** Begin *********/
        if (root == null) {
            return;
        }
        inOrder(root.leftChild);
        System.out.println(root.item);
        inOrder(root.rightChild);
        /********** End *********/
    }
    /**
     * 根据二叉树的性质,以数组arr从左至右构建一颗满二叉树
     *
     * @param arr
     * @param n
     * @return
     */
    public TreeNode createTree(int arr[]) {
        TreeNode tmp[] = new TreeNode[arr.length + 1];
        for (int k = 1; k <= arr.length; k++) {
            TreeNode node = new TreeNode(arr[k - 1]);
            tmp[k] = node;
            if (k == 1) {
                root = node;
            } else {
                int j = k / 2;
                if (k % 2 == 0) {
                    tmp[j].leftChild = node;
                } else {
                    tmp[j].rightChild = node;
                }
            }
        }
        return root;
    }
    public static class TreeNode {
        private TreeNode leftChild;
        private TreeNode rightChild;
        private int item;
        public TreeNode(int item) {
            this(null, null, item);
        }
        public TreeNode(TreeNode leftChild, TreeNode rightChild, int item) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
            this.item = item;
        }
    }
}

第3关 二叉树的实现之后序遍历

package step3;
/**
 * Created by zengpeng on 2018/2/12.
 */
public class BinaryTree {
    private TreeNode root;//根节点
    public BinaryTree() {
        root = null;
    }
    public void postOrder(TreeNode root) {
        /********** Begin *********/
        if (root == null) {
            return;
        }
        postOrder(root.leftChild);
        postOrder(root.rightChild);
        System.out.println(root.item);
        /********** End *********/
    }
    /**
     * 根据二叉树的性质,以数组arr从左至右构建一颗满二叉树
     *
     * @param arr
     * @param n
     * @return
     */
    public TreeNode createTree(int arr[]) {
        TreeNode tmp[] = new TreeNode[arr.length + 1];
        for (int k = 1; k <= arr.length; k++) {
            TreeNode node = new TreeNode(arr[k - 1]);
            tmp[k] = node;
            if (k == 1) {
                root = node;
            } else {
                int j = k / 2;
                if (k % 2 == 0) {
                    tmp[j].leftChild = node;
                } else {
                    tmp[j].rightChild = node;
                }
            }
        }
        return root;
    }
    public static class TreeNode {
        private TreeNode leftChild;
        private TreeNode rightChild;
        private int item;
        public TreeNode(int item) {
            this(null, null, item);
        }
        public TreeNode(TreeNode leftChild, TreeNode rightChild, int item) {
            this.leftChild = leftChild;
            this.rightChild = rightChild;
            this.item = item;
        }
    }
}

六、Java 数据结构之排序

第1关:选择排序

package step1;
/**
 * Created by sykus on 2018/3/20.
 */
public class SelectionSort {
    /**
     * 选择排序
     *
     * @param arr
     */
    public static void sort(int arr[]) {
        /********** Begin *********/
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[i]) {
                    int tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                }
            }
            print(arr);
        }
        /********** End *********/
    }
    private static void print(int arr[]) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

第2关 插入排序

package step2;
/**
 * Created by sykus on 2018/3/20.
 */
public class InsertionSort {
    public static void sort(int arr[]) {
        /********** Begin *********/
        for (int i = 1; i < arr.length; i++) {
            int j = i;
            int tmp = arr[j];
            while (j > 0 && tmp < arr[j - 1]) {
                arr[j] = arr[j - 1];
                j--;
            }
            arr[j] = tmp;
            print(arr);
        }
        /********** End *********/
    }
    private static void print(int arr[]) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

第3关 归并排序

package step3;
/**
 * Created by sykus on 2018/3/20.
 */
public class MergeSort {
    /**
     * lo, hi都是指下标
     */
    public static void sort(int arr[], int lo, int hi) {
        if (lo < hi) {
            int mid = (lo + hi) / 2;
            sort(arr, lo, mid);
            sort(arr, mid + 1, hi);
            merge(arr, lo, mid, hi);
            print(arr);
        }
    }
    private static void merge(int arr[], int p, int q, int r) {
        /********** Begin *********/
        int n1 = q - p + 1;
        int n2 = r - q;
        int L[] = new int[n1 + 1];
        int R[] = new int[n2 + 1];
        for (int i = 0; i < n1; i++) {
            L[i] = arr[p + i];
        }
        for (int j = 0; j < n2; j++) {
            R[j] = arr[q + j + 1];
        }
        L[n1] = Integer.MAX_VALUE;
        R[n2] = Integer.MAX_VALUE;
        int i = 0, j = 0;
        for (int k = p; k <= r; k++) {
            if (L[i] <= R[j]) {
                arr[k] = L[i];
                i++;
            } else {
                arr[k] = R[j];
                j++;
            }
        }
        /********** End *********/
    }
    private static void print(int arr[]) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

第4关 快速排序

package step4;
/**
 * Created by sykus on 2018/3/20.
 */
public class QuickSort {
    public void sort(int arr[], int low, int high) {
        /********** Begin *********/
        int i = low;
        int j = high + 1;
        int povit = arr[low];
        while (i < j) {
            while (j > low && arr[--j] >= povit) ;
            while (i < high && arr[++i] <= povit) ;
            if (i>=j)break;
            int temp = arr[j];
            arr[j] = arr[i];
            arr[i] = temp;
            print(arr);
        }
        int temp = arr[j];
        arr[j] = arr[low];
        arr[low] = temp;
        print(arr);
        if (i > low) sort(arr, low, j - 1);
        if (j < high) sort(arr, j + 1, high);
        /********** End *********/
    }
    private static void print(int arr[]) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

第5关 堆排序

package step5;
/**
 * Created by sykus on 2018/3/20.
 */
public class HeapSort {
    public static void sort(int arr[]) {
        /********** Begin *********/
        int n = arr.length;
        for (int k = n / 2; k >= 1; k--) {
            int l = k;
            while (2 * l <= n) {
                int j = 2 * l;
                if (j < n && arr[j - 1] < arr[j + 1 - 1]) j++;
                if (arr[l - 1] > arr[j - 1]) break;
                int tmp = arr[l - 1];
                arr[l - 1] = arr[j - 1];
                arr[j - 1] = tmp;
                l = j;
            }
        }
        while (n > 1) {
            int tmp = arr[0];
            arr[0] = arr[n - 1];
            arr[n - 1] = tmp;
            int k = 1;
            n--;
            while (2 * k <= n) {
                int j = 2 * k;
                if (j < n && arr[j - 1] < arr[j]) j++;
                if (arr[k - 1] > arr[j - 1]) break;
                tmp = arr[k - 1];
                arr[k - 1] = arr[j - 1];
                arr[j - 1] = tmp;
                k = j;
            }
            print(arr);
        }
        /********** End *********/
    }
    private static void print(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

七、Java 数据结构之图

第1关 图的表示

package step1;
import java.util.ArrayList;
public class Graph {
    private int V;//顶点数
    private int E;//边数
    private ArrayList<Integer>[] adj;//邻接表
    public Graph(int v) {
        if (v < 0) throw new IllegalArgumentException("Number of vertices must be nonnegative");
        V = v;
        E = 0;
        adj = new ArrayList[V + 1];
        for (int i = 0; i <= this.V; i++) {
            adj[i] = new ArrayList<Integer>();
        }
    }
    public void addEdge(int v, int w) {
        /********** Begin *********/
        adj[v].add(w);
        adj[w].add(v);
        E++;
        /********** End *********/
    }
    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append(V + " 个顶点, " + E + " 条边n");
        for (int v = 1; v <= V; v++) {
            s.append(v + ": ");
            for (int w : adj[v]) {
                s.append(w + " ");
            }
            s.append("n");
        }
        return s.toString();
    }
}

第2关 深度优先搜索

package step2;
import java.util.ArrayList;
public class DFSGraph {
    private boolean[] marked;
    private int V;//顶点数
    private int E;//边数
    private ArrayList<Integer>[] adj;//邻接表
    public DFSGraph(int v) {
        if (v < 0) throw new IllegalArgumentException("Number of vertices must be nonnegative");
        V = v;
        E = 0;
        adj = new ArrayList[V + 1];
        marked = new boolean[V + 1];
        for (int i = 0; i <= this.V; i++) {
            adj[i] = new ArrayList<Integer>();
        }
    }
    public void addEdge(int v, int w) {
        adj[v].add(w);
        adj[w].add(v);
        E++;
    }
    public void DFS(int v) {
        /********** Begin *********/
        marked[v] = true;
        System.out.print(v + " ");
        for (int w : adj[v]) {
            if (!marked[w]) {
                DFS(w);
            }
        }
        /********** End *********/
    }
    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append(V + " 个顶点, " + E + " 条边n");
        for (int v = 1; v <= V; v++) {
            s.append(v + ": ");
            for (int w : adj[v]) {
                s.append(w + " ");
            }
            s.append("n");
        }
        return s.toString();
    }
}

第3关 广度优先搜索

package step3;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class BFSGraph {
    private int V;//顶点数
    private int E;//边数
    private boolean[] marked;
    private ArrayList<Integer>[] adj;//邻接表
    public BFSGraph(int v) {
        if (v < 0) throw new IllegalArgumentException("Number of vertices must be nonnegative");
        V = v;
        E = 0;
        adj = new ArrayList[V + 1];
        marked = new boolean[V + 1];
        for (int i = 0; i <= this.V; i++) {
            adj[i] = new ArrayList<Integer>();
        }
    }
    public void addEdge(int v, int w) {
        adj[v].add(w);
        adj[w].add(v);
        E++;
    }
    public void BFS(int s) {
        /********** Begin *********/
        Queue<Integer> que = new LinkedList<>();
        que.offer(s);
        marked[s] = true;
        while (!que.isEmpty()) {
            int v = que.poll();
            System.out.print(v + " ");
            for (int w : adj[v]) {
                if (!marked[w]) {
                    que.offer(w);
                    marked[w] = true;
                }
            }
        }
        /********** End *********/
    }
    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append(V + " 个顶点, " + E + " 条边n");
        for (int v = 1; v <= V; v++) {
            s.append(v + ": ");
            for (int w : adj[v]) {
                s.append(w + " ");
            }
            s.append("n");
        }
        return s.toString();
    }
}

第4关 单源最短路径

package step4;
import java.util.*;
public class ShortestPath {
    private int V;//顶点数
    private int E;//边数
    private int[] dist;
    private ArrayList<Integer>[] adj;//邻接表
    private int[][] weight;//权重
    public ShortestPath(int v, int e) {
        V = v;
        E = e;
        dist = new int[V + 1];
        adj = new ArrayList[V + 1];
        weight = new int[V + 1][V + 1];
        for (int i = 0; i <= this.V; i++) {
            adj[i] = new ArrayList<Integer>();
        }
    }
    public void addEdge(int u, int v, int w) {
        adj[u].add(v);
        adj[v].add(u);
        weight[u][v] = weight[v][u] = w;
    }
    public int[] Paths(int source) {
        /********** Begin *********/
        Queue<Integer> Q = new LinkedList<Integer>();
        dist[source] = 0;
        for (int i = 1; i <= V; i++) {
            if (i != source) {
                dist[i] = Integer.MAX_VALUE;
            }
            Q.offer(i);
        }
        while (!Q.isEmpty()) {
            int minV = Integer.MAX_VALUE;
            int v = source;
            for (int i = 0; i < Q.size(); i++) {
                int index = ((LinkedList<Integer>) Q).get(i);
                if (dist[index] < minV) {
                    minV = dist[index];
                    v = index;
                }
            }
            Q.poll();
            Q.remove(v);
            for (int u : adj[v]) {
                int alt = dist[v] + weight[v][u];
                if (alt < dist[u]) {
                    dist[u] = alt;
                }
            }
        }
        return dist;
        /********** End *********/
    }
    /**
     * 打印源点到所有顶点的距离,INF为无穷大
     *
     * @param dist
     */
    public void print(int[] dist) {
        for (int i = 1; i <= V; i++) {
            if (dist[i] == Integer.MAX_VALUE) {
                System.out.print("INF ");
            } else {
                System.out.print(dist[i] + " ");
            }
        }
    }
}

最后的图的代码来只班级内同学的支持!!

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>