关于android:Java-八大数据结构之数组栈队列

38次阅读

共计 7744 个字符,预计需要花费 20 分钟才能阅读完成。

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: 咱们都是阳沟里的虫子, 但总还是得有人俯视星空。

正文完
 0