java面试题数据结构和算法分析unity3D技术分享

程序员面试闯关(二):数据结构考点与细节分析

2016-08-24  本文已影响469人  androidjp

上一篇文章程序员面试闯关(一):字符串匹配+排序+查找列举说明了各种常见的排序算法等算法基础,这里,主要分析下数据结构相关的基础和注意点。

一、线性表

1. 数组(顺序存储结构)

  1. 效率分析
  1. 整体分析:
    • 适合:存数据,取数据【无须为了表示表中元素之间的逻辑关系而增加额外的存储空间,可以快速地存取表中任一位置的元素】
    • 不适合:插入和删除数据【需要频繁移动元素】

2. 链表(链式存储结构)

  1. 头指针与头结点的异同:
  1. 效率分析
  1. 优势:
  1. 细分

二、栈和队列

1. 栈

2. 队列

三、树

1. 各种概念重温

2. 一般树的存储结构

3. 二叉树

四、图

1. 定义:G(V【顶点集合】, E【边的集合】)

2. 相关概念

  1. 完全图:任意两个点之间有边的图
  2. 简单图:无重复的边或顶点到自身的边
  3. 度:顶点的边数

3. 图的存储结构

邻接矩阵和邻接表的比较:

五、二叉树和图的各个常考方法代码汇总(代码可直接复制运行)

1. 二叉树各个方法

package basic.tree;

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

/**
 * 二叉树
 * Created by androidjp on 16/8/17.
 */
public class BiTree {
    public String data;
    public BiTree left;
    public BiTree right;

    public static Scanner scanner = new Scanner(System.in);

    /**
     * 以 先序遍历 的顺序进行元素插入
     *
     * @return 创建好的二叉树
     */
    public static BiTree createTree() {
        String s = scanner.next();
        char ch = s.charAt(0);
        if (ch == '#') {
            return null;
        }
        BiTree root = new BiTree();
        root.data = s;
        root.left = null;
        root.right = null;

        //递归进行插入
        root.left = createTree();
        root.right = createTree();

        return root;
    }

    /**
     * 先序遍历二叉树
     *
     * @param tree
     */
    public static void preTraverse(BiTree tree) {
        if (tree == null)
            return;
        System.out.print(tree.data + " ");
        preTraverse(tree.left);
        preTraverse(tree.right);

    }

    /**
     * 中序遍历二叉树
     *
     * @param tree
     */
    public static void orderTraverse(BiTree tree) {
        if (tree == null)
            return;
        orderTraverse(tree.left);
        System.out.print(tree.data +" ");
        orderTraverse(tree.right);

    }

    /**
     * 后序遍历二叉树
     *
     * @param tree
     */
    public static void postTraverse(BiTree tree) {
        if (tree == null)
            return;
        postTraverse(tree.left);
        postTraverse(tree.right);
        System.out.print(tree.data + " ");
    }

    /**
     * 二叉树的深度优先遍历
     * 【二叉树不同于图,图需要标记元素是否已经被遍历过,因为可能存在环,而树则不用考虑环的问题,于是少了判断这一步】
     * 使用栈 遍历
     *
     * @param tree
     */
    public static void depthFirstTraverse(BiTree tree) {
        Stack<BiTree> stack = new Stack<>();
        stack.push(tree);
        while (!stack.empty()) {
            tree = stack.peek();
            System.out.print(tree.data + " ");
            stack.pop();
            //注意 元素入栈先后顺序: right -> left
            if (tree.right!= null){
                stack.push(tree.right);
            }
            if (tree.left != null) {
                stack.push(tree.left);
            }
        }
    }

    /**
     * 广度优先遍历(也称为:层次遍历)
     * 利用队列
     * @param tree
     */
    public static void breadFirstTraverse(BiTree tree){
        Queue<BiTree> queue = new ArrayDeque<>();
        queue.add(tree);
        while(!queue.isEmpty()){
            tree = queue.poll();
            System.out.print(tree.data + " ");
            if (tree.left!=null){
                queue.add(tree.left);
            }
            if (tree.right!=null){
                queue.add(tree.right);
            }
        }
    }


    public static void main(String[] args) {
        BiTree tree = new BiTree();
        ///(根节点 -> 左孩子 -> 右孩子)创建二叉树,如输入: 1 2a 3a # 4b # # 3b # # 2b # #
        tree = createTree();
        BiTree ptr = tree;

        //先序遍历
        preTraverse(ptr);
        System.out.println();

        //中序遍历
        ptr = tree;
        orderTraverse(ptr);
        System.out.println();

        //后序遍历
        ptr = tree;
        postTraverse(ptr);
        System.out.println();

        //深度优先遍历
        ptr = tree;
        depthFirstTraverse(ptr);
        System.out.println();

        //广度优先遍历
        ptr = tree;
        breadFirstTraverse(ptr);
        System.out.println();
    }
}

2. 图的广度和深度优先比遍历(邻接矩阵表示权值)

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * 使用邻接矩阵来表示'边'的图结构
 * Created by androidjp on 16/9/8.
 */
public class MyGraph<V> {
    private ArrayList<V> vertexList;//点集合
    private int[][] edges; //邻接矩阵表示的边集合
    private int numOfEdges; //边数

    public MyGraph(int num){
        vertexList  = new ArrayList(num);
        edges = new int[num][num];
        numOfEdges = 0;
    }

    ///边数
    public int getNumOfEdges(){
        return this.numOfEdges;
    }

    ///结点数
    public int getNumOfVertex(){
        return this.vertexList.size();
    }

    //获取第i个结点
    public V getVertex(int i){
        return this.vertexList.get(i);
    }

    //获取i、j两个结点之间的权值
    public int getWeight(int i, int j){
        return this.edges[i][j];
    }

    //插入结点
    public void insertVertex(V vertex) {
        vertexList.add(vertexList.size(),vertex);
    }

    //插入结点
    public void insertEdge(int v1,int v2,int weight) {
        edges[v1][v2]=weight;
        numOfEdges++;
    }

    //删除结点
    public void deleteEdge(int v1,int v2) {
        edges[v1][v2]=0;
        numOfEdges--;
    }

    //得到第一个邻接结点的下标
    public int getFirstNeighbor(int index) {
        for(int j=0;j<vertexList.size();j++) {
            if (edges[index][j]>0) {
                return j;
            }
        }
        return -1;
    }

    //根据前一个邻接结点的下标来取得下一个邻接结点
    public int getNextNeighbor(int v1,int v2) {
        for (int j=v2+1;j<vertexList.size();j++) {
            if (edges[v1][j]>0) {
                return j;
            }
        }
        return -1;
    }

    //私有函数,深度优先遍历
    private void depthFirstSearch(boolean[] isVisited,int  i) {
        //首先访问该结点,在控制台打印出来
        System.out.print(getVertex(i)+"  ");
        //置该结点为已访问
        isVisited[i]=true;

        int w=getFirstNeighbor(i);
        while (w!=-1) {
            if (!isVisited[w]) {
                depthFirstSearch(isVisited,w);
            }
            w=getNextNeighbor(i, w);
        }
    }

    //对外公开函数,深度优先遍历,与其同名私有函数属于方法重载
    public void depthFirstSearch() {
        boolean[] isVisited = new boolean[getNumOfVertex()];
        for(int i=0;i<isVisited.length;i++)
            isVisited[i] = false;

        for(int i=0;i<getNumOfVertex();i++) {
            //因为对于非连通图来说,并不是通过一个结点就一定可以遍历所有结点的。
            if (!isVisited[i]) {
                depthFirstSearch(isVisited,i);
            }
        }
    }

    //私有函数,广度优先遍历
    private void broadFirstSearch(boolean[] isVisited,int i) {
        int u,w;
        LinkedList queue=new LinkedList();

        //访问结点i
        System.out.print(getVertex(i)+"  ");
        isVisited[i]=true;
        //结点入队列
        queue.addLast(i);
        while (!queue.isEmpty()) {
            u=((Integer)queue.removeFirst()).intValue();
            w=getFirstNeighbor(u);
            while(w!=-1) {
                if(!isVisited[w]) {
                    //访问该结点
                    System.out.print(getVertex(w)+"  ");
                    //标记已被访问
                    isVisited[w]=true;
                    //入队列
                    queue.addLast(w);
                }
                //寻找下一个邻接结点
                w=getNextNeighbor(u, w);
            }
        }
    }

    //对外公开函数,广度优先遍历
    public void broadFirstSearch() {
        boolean[] isVisited = new boolean[getNumOfVertex()];
        for(int i=0;i<isVisited.length;i++)
            isVisited[i] = false;
        for(int i=0;i<getNumOfVertex();i++) {
            if(!isVisited[i]) {
                broadFirstSearch(isVisited, i);
            }
        }
    }



    public static void main(String args[]) {
        int n = 8, e = 9;//分别代表结点个数和边的数目
        String labels[] = {"1", "2", "3", "4", "5", "6", "7", "8"};//结点的标识
        MyGraph<String> graph = new MyGraph<String>(n);
        for (String label : labels) {
            graph.insertVertex(label);//插入结点
        }
        //插入九条边
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(3, 7, 1);
        graph.insertEdge(4, 7, 1);
        graph.insertEdge(2, 5, 1);
        graph.insertEdge(2, 6, 1);
        graph.insertEdge(5, 6, 1);
        graph.insertEdge(1, 0, 1);
        graph.insertEdge(2, 0, 1);
        graph.insertEdge(3, 1, 1);
        graph.insertEdge(4, 1, 1);
        graph.insertEdge(7, 3, 1);
        graph.insertEdge(7, 4, 1);
        graph.insertEdge(6, 2, 1);
        graph.insertEdge(5, 2, 1);
        graph.insertEdge(6, 5, 1);

        System.out.println("深度优先搜索序列为:");
        graph.depthFirstSearch();
        System.out.println();
        System.out.println("广度优先搜索序列为:");
        graph.broadFirstSearch();
    }
}
上一篇下一篇

猜你喜欢

热点阅读