Java 八大数据结构之数组,栈,队列

一:介绍
数据结构是计算机存储,组织数据的形式,指相互之间存在一种或多种特定的数据元素的汇合

二:数组(Array)
数组是用来寄存同一种数据类型的汇合,留神只能寄存同一种数据类型(Object类型数组除外)
数组申明
形式一:
数据类型 [] 数组名称=new 数据类型[数组长度];

//申明一个数组长度为5,只能寄存int类型的数据 int[] num=new int[5]; //给数组第二个元素赋值        num[1]=12;        //输入第一个元素和第二个元素,后果0,12默认没赋值的是0        System.out.println(num[0]);        System.out.println(num[1]);        //后果        System.out: 0        System.out: 12                 String[] ss=new String[4];        ss[0]="Rocky";        System.out.println(ss[0]);        System.out.println(ss[1]);        //后果        System.out: Rocky        System.out: null   //能够看到:int:默认是0,String:默认是null,boolean:默认是flase

形式二:
数据类型 [] 数组名称 = {数组元素1,数组元素2,......}

 int[] ss= {1,4,3,5,7,3};        for (int i=0;i<ss.length;i++){            System.out.println(ss[i]);        }            

自定义一个数组的实现,实现数组的增删改查

public class MyArray {    //定义一个数组    private int[] intArray;    //定义数组的理论无效长度    private int elems;    //定义数组的最大长度    private int length;    //默认结构一个长度为50的数组    public MyArray() {        elems = 0;        length = 50;        intArray = new int[length];    }    //构造函数,初始化一个长度为length 的数组    public MyArray(int length) {        elems = 0;        this.length = length;        intArray = new int[length];    }    //获取数组的无效长度    public int getSize() {        return elems;    }    //增加数组    //假如操作人是不会增加反复元素的,如果有反复元素对于前面的操作都会有影响    public boolean add(int value) {        //增加元素默认是从角标elems,0开始增加        if (elems == length) {            return false;        } else {            intArray[elems] = value;            elems++;        }        return true;    }    //依据下标获取元素,查找下标值在数组下标无效范畴内,返回下标所示意的元素,查找下标超出数组下标有效值,提醒拜访下标越界    public int get(int i) {        if (i < 0 || i > elems) {            System.out.println("拜访下标越界");        }        return intArray[i];    }    //查找元素,查找的元素如果存在则返回下标值,如果不存在,返回 -1    public int find(int searchValue) {        int i;        for (i = 0; i < elems; i++) {            if (intArray[i] == searchValue) {                break;            }        }        if (i == elems) {            return -1;        }        return i;    }    //删除元素,果要删除的值不存在,间接返回 false;否则返回true,删除胜利    public boolean delete(int value) {        int k = find(value);        if (k == -1) {            return false;        } else {            if (k == elems - 1) {                elems--;            } else {                //删除元素最要害的是遍历元素,并替换删除元素之后坐标的数值                for (int i = k; i < elems - 1; i++) {                    intArray[i] = intArray[i + 1];                }                elems--;            }            return true;        }    }    //批改数据,批改胜利返回true,批改失败返回false    public boolean modify(int oldValue, int newValue) {        int i = find(oldValue);        if (i == -1) {            System.out.println("须要批改的数据不存在");            return false;        } else {            intArray[i] = newValue;            return true;        }    }    /**     * 遍历显示元素     */    public void display() {        for (int i = 0; i < elems; i++) {            System.out.print(intArray[i] + " ");        }        System.out.println();    }}

调用

 //创立自定义封装数组构造,数组大小为4        MyArray array=new MyArray(4);        //增加4个元素        array.add(3);        array.add(5);        array.add(6);        array.add(7);        //显示数据        array.display();        //依据下标为0的元素        int i = array.get(0);        System.out.println(i);        //删除7的元素        array.delete(7);        //将元素6批改为12        array.modify(6, 12);        array.display();                //后果        System.out: 3 5 6 7         System.out: 3        System.out: 3 5 12 

数组一旦创立后,大小就固定了,不能动静扩大数组的元素个数。如果初始化你给一个很大的数组大小,那会白白浪费内存空间,如果给小了,前面数据个数减少了又增加不进去了。

二维数组
定义:二维数组其实就是一个元素为一维数组的数组;

//形式一 int a[][] = new int[3][4]; int[][] b = new int[3][4];//个别应用 int[] c[] = new int[3][3];  b[0][0]=1;   b[0][1]=5;  System.out.print(b[0][0]+",");  System.out.print(b[0][1]+","); System.out.print(b[3][6]+","); //java.lang.ArrayIndexOutOfBoundsException: length=3; index=3 //后果 System.out: 1,5, //形式二  int d[][] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}};  //遍历后果   for(int x=0;x<d.length;x++){            for(int y=0;y<d[x].length;y++){                System.out.print(d[x][y]+",");            }            System.out.println();        }        //后果System.out: 1,3,5,7,System.out: 9,11,13,15,System.out: 17,19,21,23,  //形式三  int e[][] = new int[3][];        e[0] = new int[2];        e[1] = new int[2];        e[2] = new int[2];

三:栈(Stack)
栈(英语:stack)又称为堆栈或重叠,栈作为一种数据结构,是一种只能在一端进行插入和删除操作的非凡线性表。它依照先进后出的准则存储数据,先进入的数据被压入栈底,最初的数据在栈顶,须要读数据的时候从栈顶开始弹出数据(最初一个数据被第一个读出来)。栈具备记忆作用,对栈的插入与删除操作中,不须要扭转栈底指针。
 栈是容许在同一端进行插入和删除操作的非凡线性表。容许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入个别称为进栈(PUSH),删除则称为退栈(POP)
  因为重叠数据结构只容许在一端进行操作,因此依照后进先出(LIFO, Last In First Out)的原理运作。栈也称为后进先出表。

自定义实现一个栈,能够出栈,入栈,能够扩容,能够拜访栈顶数据

public class MyStack {    //存储元素的数组,申明为Object类型能存储任意类型的数据    private Object[] elementData;//数组    private int maxSize;//栈最大数量    private int top;//栈顶的指针    public MyStack() {        this.elementData = new Object[10];        this.top = -1;        this.maxSize = 10;    }    public MyStack(int initialCapacity) {        if (initialCapacity < 0) {            throw new IllegalArgumentException("栈初始容量不能小于0: " + initialCapacity);        }        this.elementData = new Object[initialCapacity];        this.maxSize = initialCapacity;        top = -1;    }    //压入数据    public Object push(Object value) {        //是否须要扩容        isGrow(top + 1);        elementData[++top] = value;        return value;    }    //弹出栈顶数据    public Object pop() {        Object obj = peek();        remove(top);        return obj;    }    //拜访栈顶数据    public Object peek() {        if(top == -1){            throw new EmptyStackException();        }        return elementData[top];    }    //判断栈是否为空    public boolean isEmpty() {        return (top == -1);    }    //删除栈顶元素    public void remove(int top){        //栈顶元素置为null        elementData[top] = null;        this.top--;    }    //判断栈是否满了    public boolean isFull() {        return (top == maxSize - 1);    }    /**     * 是否须要扩容,如果须要,则扩充一倍并返回true,不须要则返回false     *     * @param minCapacity     * @return     */    public boolean isGrow(int minCapacity) {        int oldCapacity = maxSize;        //如果以后元素压入栈之后总容量大于后面定义的容量,则须要扩容        if (minCapacity >= oldCapacity) {            //定义扩充之后栈的总容量            int newCapacity = 0;            //栈容量扩充两倍(左移一位)看是否超过int类型所示意的最大范畴            if ((oldCapacity << 1) - Integer.MAX_VALUE > 0) {                newCapacity = Integer.MAX_VALUE;            } else {                newCapacity = (oldCapacity << 1);//左移一位,相当于*2            }            this.maxSize = newCapacity;            int[] newArray = new int[maxSize];            elementData = Arrays.copyOf(elementData, maxSize);            return true;        } else {            return false;        }    }}

调用

MyStack stack = new MyStack(3);        stack.push(2);        System.out.println(stack.peek());        stack.push("Rocky");        stack.push(true);        stack.push("fight");//超过了3个主动扩容       //拜访栈顶数据        System.out.println(stack.peek());        stack.pop();        stack.pop();        stack.pop();        System.out.println(stack.peek());        //判断栈是否为空        boolean aa=stack.isEmpty();        System.out.println(aa);                                //后果        System.out: 2        System.out: fight        System.out: 2       System.out: false             //利用栈实现字符翻转       MyStack myStack = new MyStack();                String str = "HelloWorld";                char[] cha = str.toCharArray();                for(char c : cha){                    myStack.push(c);                }                while(!myStack.isEmpty()){                    System.out.println(myStack.pop());                }

四:队列(Queue)
队列(queue)是一种非凡的线性表,非凡之处在于它只容许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
 队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只容许在一端插入,在另一端删除,所以只有最早进入队列的元素能力最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。

1.与栈不同的是,队列中的数据不总是从数组的0下标开始的,移除一些队头front的数据后,队头指针会指向一个较高的下标地位

2.咱们再设计时,队列中新增一个数据时,队尾的指针rear 会向上挪动,也就是向下标大的方向。移除数据项时,队头指针 front 向上挪动。那么这样设计如同和现实情况相同,比方排队买电影票,队头的买完票就来到了,而后队伍整体向前挪动。在计算机中也能够在队列中删除一个数之后,队列整体向前挪动,然而这样做效率很差。咱们抉择的做法是挪动队头和队尾的指针。
自定队列实现增删
3.如果向第②步这样挪动指针,置信队尾指针很快就挪动到数据的最末端了,这时候可能移除过数据,那么队头会有空着的地位,而后新来了一个数据项,因为队尾不能再向上挪动了,那该怎么办呢?

4.为了防止队列不满却不能插入新的数据,咱们能够让队尾指针绕回到数组开始的地位,这也称为“循环队列”。

弄懂原理之后实现:

public class MyQueue {    private Object[] queArray;    //队列总大小    private int maxSize;    //前端指针,队头指针    private int front;    //后端指针,队尾指针    private int rear;    //队列中元素的理论数量    private int nItems;        public MyQueue(int size){        maxSize=size;        queArray=new Object[maxSize];        front=0;        rear=-1;        nItems=0;            }        //队列新增数据    public void insert(int value){        if (isFull()){            System.out.println("队列已满!!!");        }else {            //如果队尾部指向顶了,那么循环回来,执行队列的第一个元素            if (rear==maxSize-1){                rear=-1;            }            //队尾指针加1,而后在队尾指针处插入新的数据            queArray[++rear] = value;            nItems++;        }    }    //移除数据    public Object remove(){        Object removeValue = null ;        if (!isEmpty()){            removeValue=queArray[front];            //把队头数据置为空            queArray[front]=null;            //队头指针+1            front++;            if (front==maxSize){                //如果队头为总容量大小,置为0                front=0;            }            nItems--;            return removeValue;        }        return removeValue;    }    //返回队列的大小    public int getSize(){        return nItems;    }    //查看对头数据    public Object peekFront(){        return queArray[front];    }    //判断队列是否为空    public boolean isEmpty(){        return (nItems ==0);    }    //判断队列是否满了    public boolean isFull(){        return (nItems == maxSize);    }}

调用

      MyQueue queue = new MyQueue(3);                queue.insert(1);                queue.insert(2);                queue.insert(3);//queArray数组数据为[1,2,3]                System.out.println(queue.peekFront()); //1                queue.remove();//queArray数组数据为[null,2,3]                System.out.println(queue.peekFront()); //2                queue.insert(4);//queArray数组数据为[4,2,3]                //为什么是[4,2,3]不是[2,3,4]                //应为队列队尾满了当前会循环到后面去                /* 如果队尾部指向顶了,那么循环回来,执行队列的第一个元素            if (rear==maxSize-1){                rear=-1;                //这个决定的,队尾的指针变了,到了最初了,就会循环回去,然而队头的指针是没有变动的            }*/                System.out.println(queue.peekFront()); //2,应为队头指针没有变动                queue.remove();//queArray数组数据为[4,null,3]                queue.remove();//queArray数组数据为[4,null,null]                queue.insert(5);//queArray数组数据为[4,5,null]                queue.insert(6);//queArray数组数据为[4,5,6]                queue.insert(7);//队列已满,queArray数组数据为[4,5,6]                System.out.println(queue.peekFront()); //4                                //后果              System.out: 1              System.out: 2              System.out: 2              System.out: 队列已满!!!              System.out: 4

 请大家先看看什么是前缀表达式,中断表达式,后缀表达式:这三种表达式其实就是算术表达式的三种写法,以 3+4-5为例
 前缀表达式:操作符在操作数的后面,比方 +-543(计算机从右向左扫描)
 中断表达式:操作符在操作数的两头,这也是人类最容易辨认的算术表达式 3+4-5
 后缀表达式:操作符在操作数的前面,比方 34+5-(计算机从左向右扫描)

END:咱们都是阳沟里的虫子,但总还是得有人俯视星空。