zoukankan      html  css  js  c++  java
  • leetcode常规算法题复盘(基础篇)——线性表java实现

    根据清华大学出版社的《数据结构及应用算法教程》第二章内容,线性表包括顺序存储模式及链式存储模式,以下为根据书中内容通过java语言实现的顺序表及链表。

    其中元素类型通过泛型化进行约束。

    此处特别鸣谢CSDN爪 哇大佬的博客,地址:https://blog.csdn.net/qq_40794973/article/details/101555091?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-3&spm=1001.2101.3001.4242

    顺序表:

      1 import java.util.Arrays;
      2 /**
      3  * 顺序线性表的实现
      4  */
      5 public class LineList<E>{
      6   private int size;   //长度
      7   private Object[] array;  //底层数组
      8   private final int default_length=16; //默认长度
      9  /**
     10   * 无参构造方法
     11   */
     12   public LineList(){
     13     size = 0;
     14   //使用默认长度构造数组
     15     array = new Object[default_length];
     16   }
     17  /**
     18   * 指定长度进行构造
     19   * @param length 指定初始长度
     20   */
     21  public LineList(int length){
     22   if(length<0){
     23    throw new IllegalArgumentException("初始长度不合法:"+length);
     24   }
     25   //使用指定长度构造数组
     26   array = new Object[length];
     27  }
     28 
     29  /**
     30   * 指定初始化元素和长度进行构造
     31   * @param element 初始化元素
     32   * @param length 初始化长度
     33   */
     34  public LineList(E element,int length){
     35   if(length<1){
     36    throw new IllegalArgumentException("初始长度不合法:"+length);
     37   }
     38   //使用指定长度构造数组
     39   array = new Object[length];
     40   //初始化第一个元素
     41   array[0] = element;
     42   size++;
     43  }
     44  /**
     45   * 指定初始化元素进行构造
     46   * @param element 初始化元素
     47   */
     48  public LineList(E element){
     49   //使用默认长度初始化数组
     50   array = new Object[default_length];
     51   //初始化第一个元素
     52   array[0] = element;
     53  }
     54 
     55  /**
     56   * 获取元素个数
     57   */
     58  public int size() {
     59   return size;
     60  }
     61 
     62  /**
     63   * 判断是否为空
     64   */
     65  public boolean isEmpty() {
     66   return size==0;
     67  }
     68 
     69  /**
     70   * 判断是否包含此元素
     71   */
     72  public boolean contains(E e) {
     73   if(indexOf(e) == -1){
     74    return false;
     75   }
     76   return true;
     77  }
     78 
     79  /**
     80   * 格式化为数组
     81   */
     82  public Object[] toArray() {
     83   return Arrays.copyOf(array, size);
     84  }
     85 
     86  /**
     87   * 向线性表尾部添加一个元素
     88   * @param e
     89   * @return
     90   */
     91  public void add(E e) {
     92   extendCapacity(size+1);
     93   array[size]=e;
     94   size++;
     95  }
     96 
     97  /**
     98   * 扩容
     99   * @param length 需要的长度
    100   */
    101  private void extendCapacity(int length){
    102   //当前数组长度和需要的长度取最大
    103   int minCapacity = Math.max(array.length, length);
    104   //判断是否需要扩容
    105   if(minCapacity - array.length>0){
    106    //数组长度增加一半
    107    int newLength = array.length + array.length/2;
    108    //如果新的长度还比需求要小,将需求的长度作为数组长度
    109    if(newLength < minCapacity){
    110     newLength=minCapacity;
    111    }
    112    //数组长度不能超过Integer.Max_Value
    113    if(newLength > Integer.MAX_VALUE - 8){
    114     newLength = Integer.MAX_VALUE;
    115    }
    116    //数组扩容
    117    array = Arrays.copyOf(array, newLength);
    118   }
    119  }
    120  /**
    121   * 从线性表中移除所有此元素
    122   * @param e 需要移除的元素
    123   * @return
    124   */
    125  public void removeAll(E e) {
    126   if(e==null){
    127    for(int i=0;i<size;i++){
    128     if(array[i]==null){
    129      fastRemove(i);
    130     }
    131    }
    132   }else{
    133    for(int i=0;i<size;i++){
    134     if(e.equals(array[i])){
    135      fastRemove(i);
    136     }
    137    }
    138   }
    139  }
    140 
    141  /**
    142   * 删除索引处元素,后面的元素依次前移
    143   * @param index 需要删除的索引
    144   */
    145  private void fastRemove(int index){
    146   if(size-index-1>0){  
    147    //数组从index+1开始全部前移
    148    System.arraycopy(array, index+1, array, index, size-1);
    149   }
    150   //最后一个元素请空
    151   array[--size]=null;
    152  }
    153 
    154  /**
    155   * 清空线性表
    156   */
    157  public void clear() {
    158   //将数组全部填充为null
    159   Arrays.fill(array, null);
    160   //将元素个数改为0
    161   size=0;
    162  }
    163  /**
    164   * 获得索引处的元素
    165   * @param index
    166   * @return 索引处的元素
    167   */
    168  @SuppressWarnings("unchecked")
    169  public E get(int index) {
    170   checkIndex(index);
    171   return (E)array[index];
    172  }
    173 
    174  /**
    175   * 验证是否为索引越界
    176   * @param index
    177   */
    178  private void checkIndex(int index){
    179   if(index>=size || index<0){
    180    throw new IndexOutOfBoundsException("索引越界");
    181   }
    182  }
    183 
    184  /**
    185   * 将索引处的元素修改为新的元素
    186   * @param index 索引位置
    187   * @param element 元素
    188   * @return 原索引处的元素
    189   */
    190  @SuppressWarnings("unchecked")
    191  public E set(int index, E element) {
    192   checkIndex(index);
    193   E e = (E)array[index];
    194   array[index]=element;
    195   return e;
    196  }
    197 
    198  /**
    199   * 在指定的索引处插入指定的元素
    200   * @param index 索引位置
    201   * @param element 元素
    202   */
    203  public void add(int index, E element) {
    204   //验证索引
    205   checkIndex(index);
    206   //是否需要扩容
    207   extendCapacity(size+1);
    208   //复制数组
    209   System.arraycopy(array, index, array, index+1, size-index);
    210   array[index]=element;
    211  }
    212 
    213  /**
    214   * 移除索引处的元素
    215   * @param index 索引
    216   * @return 删除了的元素
    217   */
    218  @SuppressWarnings("unchecked")
    219  public E remove(int index) {
    220   checkIndex(index);
    221   //取得索引位置的元素
    222   E e = (E)array[index];
    223   fastRemove(index);
    224   return e;
    225  }
    226 
    227  /**
    228   * 取得元素第一次出现的位置的索引
    229   * @param e 要查找的元素
    230   * @return 如果为-1说明线性表没有这个元素
    231   */
    232  public int indexOf(E e) {
    233   if(e==null){//注意此处e==null的含义是传入了一个值为空的e值,但e并不是没有,还是应该在Object array里寻找同样为空的位置。
    234    for(int i=0;i<size;i++){
    235     if(e==array[i]){
    236      return i;
    237     }
    238    }
    239   }
    240   for(int i=0;i<size;i++){
    241    if(e.equals(array[i])){
    242     return i;
    243    }
    244   }
    245   return -1;
    246  }
    247 
    248  /**
    249   * 取得元素最后一次出现的位置的索引
    250   * @param e 要查找的元素
    251   * @return 如果为-1说明线性表没有这个元素
    252   */
    253  public int lastIndexOf(E e) {
    254   //判断元素是否为null
    255   if(e==null){    
    256    for(int i=size-1;i>=0;i--){
    257     if(e==array[i]){
    258      return i;
    259     }
    260    }
    261   }
    262   for(int i=size-1;i>=0;i--){
    263    //如果为null这里会跑出NullPoint异常
    264    //所以前面要加上验证是否为Null
    265    if(e.equals(array[i])){
    266     return i;
    267    }
    268   }
    269   return -1;
    270  }
    271 
    272  /**
    273   * 截取线性表
    274   * @param fromIndex 开始索引
    275   * @param toIndex 结束索引
    276   * @return 截取的线性表
    277   */
    278  @SuppressWarnings("unchecked")
    279  public LineList<E> subList(int fromIndex, int toIndex) {
    280   //判断开始索引是否越界
    281   if(fromIndex<0 || fromIndex >=size){
    282    throw new IndexOutOfBoundsException("开始索引越界:"+fromIndex);
    283   }
    284   //判断结束索引是否越界
    285   if(toIndex >=size || fromIndex <0){
    286    throw new IndexOutOfBoundsException("结束索引越界:"+toIndex);
    287   }
    288   //判断开始索引和结束索引是否正确
    289   if(fromIndex > toIndex){
    290    throw new IllegalArgumentException("参数不正确,开始索引应大于等于结束索引");
    291   }
    292   LineList<E> list = new LineList<E>();
    293   for(int i=fromIndex,j=toIndex;i<=j;i++){
    294    list.add((E)array[i]);
    295   }
    296   return list;
    297  }
    298 }

     链表:

    ①用常规方式实现有虚拟头结点的链表

      1 public class LinkedList<E> {
      2     private class Node {
      3         public E e;
      4         public Node next;
      5         public Node(E e, Node next) {
      6             this.e = e;
      7             this.next = next;
      8         }
      9         public Node(E e) {
     10             this(e, null);
     11         }
     12         public Node() {
     13             this(null, null);
     14         }
     15         @Override
     16         public String toString() {
     17             return e.toString();
     18         }
     19     }
     20     private Node dummyHead;
     21     private int size;
     22     public LinkedList() {
     23         dummyHead = new Node();
     24         size = 0;
     25     }
     26     // 获取链表中的元素个数
     27     public int getSize() {
     28         return size;
     29     }
     30     // 返回链表是否为空
     31     public boolean isEmpty() {
     32         return size == 0;
     33     }
     34     // 在链表的index(0-based)位置添加新的元素e
     35 // 在链表中不是一个常用的操作,练习用
     36     public void add(int index, E e) {
     37         if (index < 0 || index > size) {
     38             throw new IllegalArgumentException("Add failed. Illegal index.");
     39         }
     40         Node prev = dummyHead;
     41         for (int i = 0; i < index; i++) {
     42             prev = prev.next;
     43         }
     44         prev.next = new Node(e, prev.next);
     45         size++;
     46     }
     47     // 在链表头添加新的元素e
     48     public void addFirst(E e) {
     49         add(0, e);
     50     }
     51     // 在链表末尾添加新的元素e
     52     public void addLast(E e) {
     53         add(size, e);
     54     }
     55     // 获得链表的第index(0-based)个位置的元素
     56 // 在链表中不是一个常用的操作,练习用:
     57     public E get(int index) {
     58         if (index < 0 || index >= size) {
     59             throw new IllegalArgumentException("Get failed. Illegal index.");
     60         }
     61         Node cur = dummyHead.next;
     62         for (int i = 0; i < index; i++) {
     63             cur = cur.next;
     64         }
     65         return cur.e;
     66     }
     67     // 获得链表的第一个元素
     68     public E getFirst() {
     69         return get(0);
     70     }
     71     // 获得链表的最后一个元素
     72     public E getLast() {
     73         return get(size - 1);
     74     }
     75     // 修改链表的第index(0-based)个位置的元素为e
     76     // 在链表中不是一个常用的操作,练习用:
     77     public void set(int index, E e) {
     78         if (index < 0 || index >= size) {
     79             throw new IllegalArgumentException("Set failed. Illegal index.");
     80         }
     81         Node cur = dummyHead.next;
     82         for (int i = 0; i < index; i++) {
     83             cur = cur.next;
     84         }
     85         cur.e = e;
     86     }
     87     // 查找链表中是否有元素e
     88     public boolean contains(E e) {
     89         Node cur = dummyHead.next;
     90         while (cur != null) {
     91             if (cur.e.equals(e)) {
     92                 return true;
     93             }
     94             cur = cur.next;
     95         }
     96         return false;
     97     }
     98     // 从链表中删除index(0-based)位置的元素, 返回删除的元素
     99     // 在链表中不是一个常用的操作,练习用
    100     public E remove(int index) {
    101         if (index < 0 || index >= size) {
    102             throw new IllegalArgumentException("Remove failed. Index is illegal.");
    103         }
    104         Node prev = dummyHead;
    105         for (int i = 0; i < index; i++) {
    106             prev = prev.next;
    107         }
    108         Node retNode = prev.next;
    109         prev.next = retNode.next;
    110         retNode.next = null;
    111         //疑问:这里为什么不释放结点retNode?
    112         size--;
    113         return retNode.e;
    114     }
    115     // 从链表中删除第一个元素, 返回删除的元素
    116     public E removeFirst() {
    117         return remove(0);
    118     }
    119     // 从链表中删除最后一个元素, 返回删除的元素
    120     public E removeLast() {
    121         return remove(size - 1);
    122     }
    123     // 从链表中删除元素e
    124     public void removeElement(E e) {
    125         Node prev = dummyHead;
    126         while (prev.next != null) {
    127             if (prev.next.e.equals(e)) {
    128                 break;
    129             }
    130             prev = prev.next;
    131         }
    132         if (prev.next != null) {
    133             Node delNode = prev.next;
    134             prev.next = delNode.next;
    135             delNode.next = null;
    136             size--;
    137         }
    138     }
    139     @Override
    140     public String toString(){
    141         StringBuilder res = new StringBuilder();
    142         //Node cur = dummyHead.next;
    143         //while(cur != null){
    144         //    res.append(cur + "->");
    145         //    cur = cur.next;
    146         //}
    147         for(Node cur = dummyHead.next ; cur != null ; cur = cur.next) {
    148             res.append(cur + "->");
    149         }
    150         res.append("NULL");
    151         return res.toString();
    152     }
      }

     ②用递归的方式实现链表

      1 /**
      2  * Recursion
      3  */
      4 public class LinkedListR<E> {
      5     private class Node {
      6         public E e;
      7         public Node next;
      8         public Node(E e, Node next) {
      9             this.e = e;
     10             this.next = next;
     11         }
     12         public Node(E e) {
     13             this(e, null);
     14         }
     15         public Node() {
     16             this(null, null);
     17         }
     18         @Override
     19         public String toString() {
     20             return e.toString();
     21         }
     22     }
     23  
     24     // 在链表的递归实现中,我们不使用虚拟头结点,也能无差异的处理位置0的问题:
     25     private Node head;
     26     private int size;
     27     public LinkedListR() {
     28         head = null;
     29         size = 0;
     30     }
     31     // 获取链表中的元素个数
     32     public int getSize() {
     33         return size;
     34     }
     35     // 返回链表是否为空
     36     public boolean isEmpty() {
     37         return size == 0;
     38     }
     39     // 在链表的index(0-based)位置添加新的元素e
     40     public void add(int index, E e) {
     41         if (index < 0 || index > size) {
     42             throw new IllegalArgumentException("Add failed. Illegal index.");
     43         }
     44         head = add(head, index, e);
     45         size++;
     46     }
     47     // 在以node为头结点的链表的index位置插入元素e,递归算法
     48     private Node add(Node node, int index, E e) {
     49         if (index == 0) {
     50             return new Node(e, node);
     51         }
     52         node.next = add(node.next, index - 1, e);
     53         return node;
     54     }
     55     // 在链表头添加新的元素e
     56     public void addFirst(E e) {
     57         add(0, e);
     58     }
     59     // 在链表末尾添加新的元素e
     60     public void addLast(E e) {
     61         add(size, e);
     62     }
     63     // 获得链表的第index(0-based)个位置的元素
     64     public E get(int index) {
     65         if (index < 0 || index >= size) {
     66             throw new IllegalArgumentException("Get failed. Illegal index.");
     67         }
     68         return get(head, index);
     69     }
     70     // 在以node为头结点的链表中,找到第index个元素,递归算法
     71     private E get(Node node, int index) {
     72         if (index == 0) {
     73             return node.e;
     74         }
     75         return get(node.next, index - 1);
     76     }
     77     // 获得链表的第一个元素
     78     public E getFirst() {
     79         return get(0);
     80     }
     81     // 获得链表的最后一个元素
     82     public E getLast() {
     83         return get(size - 1);
     84     }
     85     // 修改链表的第index(0-based)个位置的元素为e
     86     public void set(int index, E e) {
     87         if (index < 0 || index >= size) {
     88             throw new IllegalArgumentException("Update failed. Illegal index.");
     89         }
     90         set(head, index, e);
     91     }
     92     // 修改以node为头结点的链表中,第index(0-based)个位置的元素为e,递归算法
     93     private void set(Node node, int index, E e) {
     94         if (index == 0) {
     95             node.e = e;
     96             return;
     97         }
     98         set(node.next, index - 1, e);
     99     }
    100     // 查找链表中是否有元素e
    101     public boolean contains(E e) {
    102         return contains(head, e);
    103     }
    104     // 在以node为头结点的链表中,查找是否存在元素e,递归算法
    105     private boolean contains(Node node, E e) {
    106         if (node == null) {
    107             return false;
    108         }
    109         if (node.e.equals(e)) {
    110             return true;
    111         }
    112         return contains(node.next, e);
    113     }
    114     // 从链表中删除index(0-based)位置的元素, 返回删除的元素
    115     public E remove(int index) {
    116         if (index < 0 || index >= size) {
    117             throw new IllegalArgumentException("Remove failed. Index is illegal.");
    118         }
    119         Pair<Node, E> res = remove(head, index);
    120         size--;
    121         head = res.getKey();
    122         return res.getValue();
    123     }
    124     // 从以node为头结点的链表中,删除第index位置的元素,递归算法
    125     // 返回值包含两个元素,删除后的链表头结点和删除的值:)
    126     private Pair<Node, E> remove(Node node, int index) {
    127         if (index == 0) {
    128             return new Pair<>(node.next, node.e);
    129         }
    130         Pair<Node, E> res = remove(node.next, index - 1);
    131         node.next = res.getKey();
    132         return new Pair<>(node, res.getValue());
    133     }
    134     // 从链表中删除第一个元素, 返回删除的元素
    135     public E removeFirst() {
    136         return remove(0);
    137     }
    138     // 从链表中删除最后一个元素, 返回删除的元素
    139     public E removeLast() {
    140         return remove(size - 1);
    141     }
    142     // 从链表中删除元素e
    143     public void removeElement(E e) {
    144         head = removeElement(head, e);
    145     }
    146     // 从以node为头结点的链表中,删除元素e,递归算法
    147     private Node removeElement(Node node, E e) {
    148         if (node == null) {
    149             return null;
    150         }
    151         if (node.e.equals(e)) {
    152             size--;
    153             return node.next;
    154         }
    155         node.next = removeElement(node.next, e);
    156         return node;
    157     }
    158     @Override
    159     public String toString() {
    160         StringBuilder res = new StringBuilder();
    161         Node cur = head;
    162         while (cur != null) {
    163             res.append(cur + "->");
    164             cur = cur.next;
    165         }
    166         res.append("NULL");
    167         return res.toString();
    168     }
    169 }

     

  • 相关阅读:
    编程经验
    GIS业务逻辑
    算法逻辑
    js中arguments的作用
    C#基础及记忆概念
    POI创建Excle
    数据库元数据分析Demo
    c3p0写连接池 Demo
    dbutils的使用Demo
    dbcp写连接池 Demo
  • 原文地址:https://www.cnblogs.com/monkiki/p/14161431.html
Copyright © 2011-2022 走看看