手记

数据结构

1.使用java中的数组


    

动态数组

public class Array<E> {
     private E[] data;
     private int size;
 
     public Array(int capacity) {
         data = (E[])new Object[capacity];
         size = 0;
     }
 
     public Array() {
         this(10);
     }
 
     public int getSize() {
         return size;
     }
 
     public int getCapacity() {
         return data.length;
     }
 
     public boolean isEmpty() {
         return size == 0;
     }
 
     public void addLast(E e) {
       add(size,e);
     }
 
     public void addFirst(E e) {
         add(0,e);
     }
 
     public void add(int index, E e) {
 
         if (index < 0 || index > size) {
             throw new IllegalArgumentException("");
         }
         if (size == data.length) {
            resize(2*data.length);
         }
         //从后向前挪
         for (int i = size - 1; i >= index; i--) {
             data[i + 1] = data[i];
         }
         data[index]=e;
         size++;
     }
 
      E get(int index){
         if(index<0||index>=size){
             throw  new IllegalArgumentException("");
         }
         return data[index];
     }
 
     void set (int index,E e){
         if(index<0||index>=size){
             throw  new IllegalArgumentException("");
         }
         data[index]=e;
     }
     //查找数组中是否存在元素e
     public boolean contains(E e){
         for (int i=0;i<size;i++){
             if(data[i].equals(e)){
                 return true;
             }
         }
         return false;
     }
     public int find(E e){
         for (int i=0;i<size;i++){
             if(data[i].equals(e)){
                 return i;
             }
         }
         return -1;
     }
     //删除
     public E remove(int index){
         if(index<0||index>=size){
             throw  new IllegalArgumentException("");
         }
         //将待删除元素存起来  用于返回
         E ret =data[index];
         //删除就是后面的直接覆盖
         for (int i=index+1;i<size;i++){
              data[i-1]=data[i];
         }
         size--;
         data[size]=null;//自动回收
         //动态减小数组
         if(size==data.length/4&& data.length/2!=0){
             resize(data.length/2);
         }
         return ret;
     }
 
     public  E removeFist(){
         return remove(0);
     }
     public  E removeLast(){
         return remove(size-1);
     }
 
     public void  removeElement(E e){
         int index=find(e);
         if (index!=-1)
             remove(index);
     }
 
     @Override
     public String toString(){
        StringBuilder res=new StringBuilder();
         res.append(String.("Array: size=%d,capacity=%d\n",size,data.length));
         res.append('[');
         for (int i=0;i<size;i++){
             res.append(data[i]);
             if (i!=size-1)
                 res.append(",");
         }
         res.append("]");
         return res.toString();
     }
 
     private void resize(int newCapacity){
         E[] newData=(E[]) new Object[newCapacity];
         for (int i=0;i<size;i++){
             newData[i]=data[i];
         }
         data=newData;
     }
 
 
 }



2.栈和栈的应用:撤销操作和系统栈

1.栈也是一种线性结构。

2.相比数组,栈对应的操作是数组的子集。

3.只能从一端添加元素,也只能从一端取出元素。

4.这一端称为栈顶。

A程序执行到A2这个位置去执行B程序,在B2这里执行c程序,c程序执行完成,去找应该执行的位置,就是B2.

package stack;
 
 import array.Array;
 
 public class ArrayStack<E> implements Stack<E> {
     //成员变量
     Array<E> array;
 
     //构造函数
     public ArrayStack(int capacity) {
         array = new Array<E>(capacity);
     }
 
     public ArrayStack() {
         array = new Array<E>();
     }
 
     @Override
     public int getSize() {
         return array.getSize();
     }
 
     @Override
     public boolean isEmpty() {
         return array.isEmpty();
     }
 
     public int getCapacity() {
         return array.getCapacity();
     }
 
     @Override
     public void push(E e) {
         array.addLast(e);
     }
     @Override
     public E pop() {
         return array.removeLast();
     }
     @Override
     public E peek() {
         return array.getLast();
     }
 
     @Override
     public String toString() {
         StringBuffer res=new StringBuffer();
         res.append("Stack: ");
         res.append("[");
         for (int i=0;i<array.getSize();i++){
             res.append(array.get(i));
             if (i!=array.getSize()-1){
                 res.append(",");
             }
         }
         res.append("] top");
          return res.toString();
     }
 
 
 }

栈的一个应用:括号匹配

首先我们声明一个stack  我们遍历字符,将左侧的括号以此压如栈中,开始遍历到右侧括号就和栈顶匹配,匹配成功就出栈,都遍历完了,栈是空的,当前这些括号是合法的。

反例:当遍历到右侧大括号时,与栈顶的中括号匹配失败了,

import java.util.Stack;
 
 public class Solution {
 
     public boolean isValid(String s) {
         Stack<Character> stack=new Stack<Character>();
         for (int i=0;i<s.length();i++){
             char c=s.charAt(i);
             if (c=='('||c=='['||c=='{'){
                 stack.push(c);
             }else {
                if (stack.isEmpty()){
                    return false;
                }
                 char topChar=stack.pop();
                 if(c==')'&& topChar!='('){
                     return false;
                 }
                 if (c==']'&& topChar!='['){
                     return false;
                 }
                 if (c=='}'&& topChar!='{'){
                     return false;
                 }
             }
         }
        return stack.isEmpty();
     }
 }

3数组队列

队列也是一种线性结构  

相比数组,队列对应的操作是数组的子集

只能从一端(队尾)添加元素,也只能从另一端(队首)取出元素。

package queue;
 
 import array.Array;
 
 public class ArrayQueue<E> implements Queue<E> {
 
     private Array<E> array;
 
     //构造函数
     public ArrayQueue(int capacity){
         array=new Array<E>(capacity);
     }
 
     public ArrayQueue(){
         array=new Array<E>();
     }
     @Override
     public int getSize() {
         return array.getSize();
     }
 
     @Override
     public boolean isEmpty() {
         return array.isEmpty();
     }
 
     public int getCapacity(){
         return array.getCapacity();
     }
 
     @Override
     public void enqueue(E e) {
         array.addLast(e);
 
     }
 
     @Override
     public E dequeue() {
        return array.removeFist();
     }
 
     @Override
     public E getFront() {
         return array.getFirst();
     }
 
     @Override
     public String toString() {
         StringBuilder res=new StringBuilder();
         res.append("Queue: ");
         res.append("front [");
         for (int i=0;i<array.getSize();i++){
             res.append(array.get(i));
             if (i!=array.getSize()-1)
                 res.append(",");
         }
         res.append("]  tail");
         return res.toString();
     }
 
     public static void main(String[] args) {
         ArrayQueue<Integer> queue=new ArrayQueue<Integer>();
         for (int i=0;i<10;i++){
             queue.enqueue(i);
             System..println(queue);
             if (i%3==2){
                 queue.dequeue();
                 System..println(queue);
             }
         }
     }
 }

4 循环队列

用数组实现对列,在出队时取走头部位置,后面的数据响应的需要往前移,所以时间复杂度是O(N)级别的,如果这些元素不移动位置,时间复杂度就会降到0(1)级别的。所以我们记录下队首和队尾的位置,就可以了。

循环对列需要两个指针,一个tail 每入队就++,取数据 front就++,为什么加循环对列:

当我们加到第7个元素时,tail+1对capacity取余  就是 0,前提是数组没有满,如果满了 就扩容。

package queue;
 
 public class LoopQueue<E> implements Queue<E> {
 
     private E[] data;
     private int front,tail;
     private int size;
 
     public LoopQueue(int capacity){
        data=(E[])new Object[capacity+1];
         front=0;
         tail=0;
         size=0;
     }
 
     public LoopQueue(){
         this(10);
     }
 
     public int getCapacity(){
         return data.length-1;
     }
 
 
     @Override
     public int getSize() {
         return size;
     }
 
     @Override
     public boolean isEmpty() {
         return front==tail;
     }
 
     @Override
     public void enqueue(E e) {
        //入队,先检查对列是否满了
         if((tail+1)%data.length==front){//满了需要扩容
             resize(getCapacity()*2);
         }
         data[tail]=e;
         tail=(tail+1)%data.length;
         size++;
     }
     private void resize(int newCapacity){
         E[] newData=(E[])new Object[newCapacity+1];//先开空间
         //将原来的数据都放入新空间中
         for (int i=0;i<size;i++){
             newData[i]=data[(i+front)%data.length];
         }
         data=newData;
         front=0;
         tail=size;
     }
 
     @Override
     public E dequeue() {
         //出队,先判断对列是否为空
         if (isEmpty()){
             throw new IllegalArgumentException("error");
         }
         E ret=data[front];
         data[front]=null;
         front=(front+1)%data.length;
         size--;
         //缩容
         if(size==getCapacity()/4 && getCapacity()/2 !=0)
             resize(getCapacity()/2);
         return ret;
     }
 
     @Override
     public E getFront() {
        if(isEmpty()){
            throw new IllegalArgumentException("error");
        }
         return data[front];
     }
 
     @Override
     public String toString() {
         StringBuilder res=new StringBuilder();
         res.append(String.("Queue: size=%d,capacity=%d\n",size,getCapacity()));
         res.append(" front [");
         for (int i=front;i!=tail;i=(i+1)%data.length){
             res.append(data[i]);
             if ((i+1)%data.length!=tail)
                 res.append(",");
         }
         res.append("] tail ");
         return res.toString();
     }
 }

5  什么是链表

package linkedList;
 
 public class LinedList<E> {
 
     //内部类
     private class Node{
         public E e;
         public Node next;
 
         //构造方法
         public Node(E e,Node next){
             this.e=e;
             this.next=next;
         }
 
         public Node(E e){
             this(e,null);
         }
         //无参构造器
         public Node(){
             this(null,null);
         }
 
         @Override
         public String toString() {
             return e.toString();
         }
     }
 
 }

带有尾针的链表:使用链表实现队列

package queue;
 
 public class LinkedListQueue<E> implements Queue<E> {
 
     private class Node {
         public E e;
         public Node next;
 
         //构造方法
         public Node(E e, Node next) {
             this.e = e;
             this.next = next;
         }
 
         public Node(E e) {
             this(e, null);
         }
 
         //无参构造器
         public Node() {
             this(null, null);
         }
 
         @Override
         public String toString() {
             return e.toString();
         }
     }
 
     private  Node head,tail;
     private  int size;
 
     @Override
     public int getSize() {
         return size;
     }
 
     @Override
     public boolean isEmpty() {
         return size==0;
     }
 
     @Override
     public void enqueue(E e) {
          if(tail==null){
              tail=new Node(e);
              head=tail;
          }else {
              tail.next=new Node(e);
              tail=tail.next;
              //头结点不要动
          }
         size ++;
     }
 
     @Override
     public E dequeue() {//出队
        if(isEmpty()){
            throw new IllegalArgumentException("error");
        }
         Node retNode=head;//出队元素的节点应该是头节点
         head=head.next;
         retNode.next=null;
         if (head ==null){
             tail=null;
         }
         size--;
         return retNode.e;
     }
 
     @Override
     public E getFront() {
         if(isEmpty()){
             throw new IllegalArgumentException("error");
         }
         return head.e;
     }
 
     @Override
     public String toString() {
         StringBuffer res=new StringBuffer();
 
         res.append("Queue :front");
         Node cur=head;
         while (cur!=null){
             res.append(cur+"->");
             cur=cur.next;
         }
         res.append("null tail");
         return res.toString();
     }
 
     public static void main(String[] args) {
        LinkedListQueue<Integer> queue=new LinkedListQueue<Integer>();
         for (int i=0;i<10;i++){
             queue.enqueue(i);
             System..println(queue);
             if (i%3==2){
                 queue.dequeue();
                 System..println(queue);
             }
         }
     }
 
 }

6 递归基础与递归的宏观语意

链表的天然递归结构性质



树结构

具体树结构  请看树结构浅析 


1人推荐
随时随地看视频
慕课网APP