Java实现《王道数据结构》伪代码

版权声明:欢迎转载,但请注明出处! https://blog.csdn.net/DavidHuang2017/article/details/88034446

一、单链表

1.结点定义

public class ListNode {
    int data;
    ListNode next;
    ListNode (int data){
        this.data=data;
    }
}

2.建立链表

    /**
     * 头插法建立链表
     * @return 链表指针
     */
    public ListNode createLsit1(){
        ListNode L=null,s;
        Scanner scanner=new Scanner(System.in);
        int x=scanner.nextInt();
        while (x!=999){
            s=new ListNode(x);
            s.next=L;
            L=s;
            x=scanner.nextInt();
        }
        return L;
    }
    
    /**
     * 尾插法建立链表
     * @return 链表指针
     */
    public ListNode createLsit2() {
        ListNode L=null , s, r=null;
        boolean isHead=true;
        Scanner scanner = new Scanner(System.in);
        int x = scanner.nextInt();
        while (x != 999) {
            s=new ListNode(x);
            if(isHead){
                L=r=s;
                isHead=false;
            }else {
                r.next=s;
                r=s;
            }
            x=scanner.nextInt();
        }
        r.next=null;
        return L;
    }

3.查找

    /**
     * 按位置查找:查找链表L中第i个结点
     * @param L 链表
     * @param i from 0
     * @return 第i个结点,查找失败返回null
     */
    ListNode getElem(ListNode L,int i){
        ListNode p=L;
        int j=0;
        if(i<0) return null;
        while (j<i){
            if(p!=null){
                p=p.next;
                j++;
            }else {//i>链表长度
                return null;
            }
        }
        return p;
    }

    /**
     * 按值查找:查找值为e的结点的位置
     * @param L 单链表
     * @param e 给定值
     * @return from 0,查找失败返回-1
     */
    int getIndex(ListNode L,int e){
        ListNode p=L;
        int i=0;
        while (p!=null&&p.data!=e){
            p=p.next;
            i++;
        }
        if(p==null)return -1;
        else return i;
    }

4.插入

//值为x的结点插到链表第i个位置
p=getElem(L,i-1);
s.next=p.next;
p.next=s;

5.删除

//将单链表的第i个结点删除
p=getElem(L,i-1);
q=p.next;
p.next=q.next;
free(q);

二、栈和队列

  栈和队列的初始化和使用见二叉树先序遍历和层次遍历代码。

三、二叉树

1.二叉树节点的定义

public class BiTNode {
    private int data;
    private BiTNode leftChild;
    private BiTNode rightChild;

    public BiTNode(int data, BiTNode leftChild, BiTNode rightChild) {
        this.data = data;
        this.leftChild = leftChild;
        this.rightChild = rightChild;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public BiTNode getLeftChild() {
        return leftChild;
    }

    public void setLeftChild(BiTNode leftChild) {
        this.leftChild = leftChild;
    }

    public BiTNode getRightChild() {
        return rightChild;
    }

    public void setRightChild(BiTNode rightChild) {
        this.rightChild = rightChild;
    }
}

2.二叉树的定义

 建造一棵如下二叉树:
image

public class BiTree {
    /**
     * 建立二叉树,返回二叉树根结点
     * 说明:注意必须逆序建立二叉树,先建立子节点,再建立双亲结点,因为双亲结点会用到子节点
     * @return 二叉树根结点
     */
    public BiTNode init() {
        BiTNode J = new BiTNode(8, null, null);
        BiTNode H = new BiTNode(4, null, null);
        BiTNode G = new BiTNode(2, null, null);
        BiTNode F = new BiTNode(7, null, J);
        BiTNode E = new BiTNode(5, H, null);
        BiTNode D = new BiTNode(1, null, G);
        BiTNode C = new BiTNode(9, F, null);
        BiTNode B = new BiTNode(3, D, E);
        BiTNode A = new BiTNode(6, B, C);
        return A;   //返回根节点
    }

    public void printNode(BiTNode node){
        System.out.print(node.getData()+" ");
    }

    /**
     * 递归先序遍历
     * @param T 根结点
     */
    public void preOrder(BiTNode T){
        if(T!=null){
            printNode(T);
            preOrder(T.getLeftChild());
            preOrder(T.getRightChild());
        }
    }

    /**
     * 递归中序遍历
     * @param T 根结点
     */
    public void inOrder(BiTNode T){
        if(T!=null){
            inOrder(T.getLeftChild());
            printNode(T);
            inOrder(T.getRightChild());
        }
    }

    /**
     * 递归后序遍历
     * @param T 根结点
     */
    public void postOrder(BiTNode T){
        if(T!=null){
            postOrder(T.getLeftChild());
            postOrder(T.getRightChild());
            printNode(T);
        }
    }

    /**
     * 非递归先序遍历,借助一个栈
     * @param T 根结点
     */
    public void preOrder2(BiTNode T){
        Stack<BiTNode> stack = new Stack<BiTNode>();//初始化栈
        BiTNode p=T;
        while (p!=null||!stack.empty()){//stack.empty()栈判空
            if(p!=null){
                printNode(p);
                stack.push(p);//入栈
                p=p.getLeftChild();
            }else {
                p=stack.pop();//出栈;p=stack.peek()获取栈顶元素
                p=p.getRightChild();
            }
        }
    }

    /**
     * 非递归中序遍历,借助一个栈
     * @param T 根结点
     */
    public void inOrder2(BiTNode T){
        Stack<BiTNode> stack = new Stack<BiTNode>();
        BiTNode p=T;
        while (p!=null||!stack.empty()){
            if(p!=null){
                stack.push(p);
                p=p.getLeftChild();
            }else {
                p=stack.pop();
                printNode(p);
                p=p.getRightChild();
            }
        }
    }

    /**
     * 非递归后序遍历,借助两个栈
     * @param T 根结点
     */
    public void postOrder2(BiTNode T){
        Stack<BiTNode> stack = new Stack<BiTNode>();
        Stack<BiTNode> output = new Stack<BiTNode>();//构造一个中间栈来存储逆后序遍历的结果
        BiTNode p=T;
        while (p!=null||!stack.empty()){
            if(p!=null){
                output.push(p);
                stack.push(p);
                p=p.getRightChild();

            }else {
                p=stack.pop();
                p=p.getLeftChild();

            }
        }
        while(output.size()>0){
            printNode(output.pop());
        }
    }

    /**
     * 层次遍历二叉树,借助一个队列
     * @param T 根结点
     */
    public void levelOrder(BiTNode T){
        Queue<BiTNode> queue = new LinkedList<BiTNode>();//初始化队列,LinkedList实现了Queue接口
        BiTNode p;
        queue.offer(T);//入队
        while (!queue.isEmpty()){//队判空
            p=queue.poll();//出队;p=queue.peek()获取队首元素
            printNode(p);
            if(p.getLeftChild()!=null){
                queue.offer(p.getLeftChild());
            }
            if(p.getRightChild()!=null){
                queue.offer(p.getRightChild());
            }
        }
    }

    /**
     * 递归获取二叉树深度
     * @param T 根结点
     * @return 二叉树深度
     */
    public int getDeepth(BiTNode T){
        if(T!=null){
            return Math.max(getDeepth(T.getLeftChild()),getDeepth(T.getRightChild()))+1;
        }else {
            return 0;
        }
    }

    public static void main(String[] args) {
        BiTree tree=new BiTree();
        tree.levelOrder(tree.init());
    }
}

四、图

 图的存储以邻接表为例,下面为图顶点的定义:

public class GraphVertex {
    private int data;//顶点值
    private List<GraphVertex> neighborList =new ArrayList<>();//该顶点的相邻顶点表

    public GraphVertex(int data) {
        this.data = data;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public List<GraphVertex> getNeighborList() {
        return neighborList;
    }

    public void addNeibor(GraphVertex v) {
        neighborList.add(v);
    }
}

 图的遍历:
 分别广度优先遍历和深度优先遍历如下无向图:
image

public class Graph {
    private List<GraphVertex> vertexList=new ArrayList<>();//顶点表
    private int vertexNum=0;//顶点数
    private boolean visited[];//访问标记数组
    private Queue<GraphVertex> queue=new LinkedList<GraphVertex>();//广度遍历辅助队列
    /**
     * 构造一张无向图,生成一个倒序的vertexList
     * @return 返回图的一个顶点
     */
    public GraphVertex init(){
        GraphVertex v5=new GraphVertex(5);
        vertexList.add(v5);

        GraphVertex v4=new GraphVertex(4);
        v4.addNeibor(v5);
        vertexList.add(v4);

        GraphVertex v3=new GraphVertex(3);
        v3.addNeibor(v4);
        v3.addNeibor(v5);
        vertexList.add(v3);

        GraphVertex v2=new GraphVertex(2);
        v2.addNeibor(v3);
        vertexList.add(v2);

        GraphVertex v1=new GraphVertex(1);
        v1.addNeibor(v2);
        v1.addNeibor(v4);
        vertexList.add(v1);
        //补全相邻顶点
        v2.addNeibor(v1);
        v3.addNeibor(v2);
        v4.addNeibor(v1);
        v4.addNeibor(v3);
        v5.addNeibor(v3);
        v5.addNeibor(v4);

        vertexNum=vertexList.size();
        visited=new boolean[vertexNum];
        return v1;
    }

    /**
     * 打印某个顶点
     * @param vertex 要打印的顶点
     */
    public void printVertex(GraphVertex vertex){
        System.out.print(vertex.getData()+" ");
    }

    /**
     * 图的遍历
     * @param mode mode==0,BFS;mode==1,DFS;
     */
    public void traverse(int mode){
        for(int i=0 ;i<vertexNum ;i++)
            visited[i]=false;//初始化访问标记数组
        for(int i=vertexNum-1;i>=0;i--){
            if(!visited[i]){//遍历图中每个未访问过的顶点所在的连通分量
                if(mode==0) BFS(vertexList.get(i));
                else if(mode==1) DFS(vertexList.get(i));
            }
        }
    }

    /**
     * 广度优先遍历一个连通分量,借助一个队列
     * @param v 遍历起始顶点
     */
    public void BFS(GraphVertex v){
        printVertex(v);
        visited[vertexList.indexOf(v)]=true;
        queue.offer(v);

        while(!queue.isEmpty()){
            v=queue.poll();
            for (int i=0;i<v.getNeighborList().size();i++){
                //访问出队顶点的所有未访问过的相邻顶点
                GraphVertex w=v.getNeighborList().get(i);
                if(!visited[vertexList.indexOf(w)]){
                    printVertex(w);
                    visited[vertexList.indexOf(w)]=true;
                    queue.offer(w);
                }
            }
        }
    }

    /**
     * 深度优先遍历一个连通分量
     * @param v 遍历起始顶点
     */
    public void DFS(GraphVertex v){
        printVertex(v);
        visited[vertexList.indexOf(v)]=true;

        for (int i=0;i<v.getNeighborList().size();i++){
            GraphVertex w=v.getNeighborList().get(i);//v未访问过的相邻顶点
            if(!visited[vertexList.indexOf(w)]){
                DFS(w);
            }
        }
    }

    public static void main(String[] args) {
        Graph graph=new Graph();
        graph.init();
        graph.traverse(0);
        System.out.println();
        graph.traverse(1);
    }
}
1 2 4 3 5 
1 2 3 4 5 

 说明:上例中,vertexList={5,4,3,2,1},对应访问标记数组下标0,1,2,3,4;
遍历是从顶点1开始的。

五、查找

public class Search {
    /**
     * 顺序查找
     * @param a 查找表
     * @param key 关键字
     * @return 与key相等元素的下标
     */
    public static int seq_search(int a[],int key){
        int n=a.length;
        int i;
        for(i=n-1;i>=0&&a[i]!=key;i--);//从后往前;为了避免数组越界异常i>=0必须加上
        return i;
    }

    /**
     * 二分(折半)查找,只适用于有序的顺序表
     * @param a 查找表
     * @param key 关键字
     * @return 与key相等元素的下标
     */
    public static int bin_search(int a[],int key){
        int low=0,high=a.length-1,mid;
        while (low<=high){
            mid=(low+high)/2;
            if(key==a[mid]) return mid;
            else if(key<a[mid]) high=mid-1;
            else low=mid+1;
        }
        return -1;
    }

    public static void main(String[] args) {
        int a[]={2,5,8,3,1,4};
        int b[]={1,2,3,4,5,8};

        for(int i=0;i<a.length;i++)System.out.print(a[i]+" ");
        System.out.println();
        Scanner scanner=new Scanner(System.in);
        int key=scanner.nextInt();
        System.out.println("顺序查找结果:"+seq_search(a,key));

        for(int i=0;i<b.length;i++)System.out.print(b[i]+" ");
        System.out.println();
        key=scanner.nextInt();
        System.out.println("二分查找结果:"+bin_search(b,key));

    }
}
2 5 8 3 1 4 
0
顺序查找结果:-1
1 2 3 4 5 8 
0
二分查找结果:-1

六、内部排序

 详见上一章《经典的8个内部排序算法》。

ps:以上java代码实现基于《王道-数据结构》伪代码。

猜你喜欢

转载自blog.csdn.net/DavidHuang2017/article/details/88034446