数据结构基础学习之线性表

2019-04-05  本文已影响0人  JiaJianHuang

线性表的学习

学习目标

1. 线性表:
public interface IList<E>{
    void clear();//线性表清空操作
    boolean isEmpty();// 判空
    int size(); //长度
    E get(int i);//通过下标获取元素
    void insert(int i,E t);// 插入元素到特定位置
    void remove(int i);// 移除元素
    int indexOf(E t);// 查找元素
    void display();//打印元素
}
2. 线性表顺序存储结构:
3. 顺序表基本实现和分析
  1. 删除操作实现及分析

    public T remove(int i) {
        // 首先,先判度下标 i 是否合法
        if (i < 0 || i > this.lenght)
            throw new IndexOutOfBoundsException("Index: " + i + ", Size: " + this.lenght);
        //获取删除的元素
        T removeObj = (T) objects[i];
        //把下标为i及其后的元素,往前移移一位
        for (int j = i; j < this.lenght - 1; j++) {
            objects[j] = objects[j + 1];
        }
        //把最后一个元素置空,帮助垃圾回收
        objects[lenght - 1] = null;
        //当前线性表长度减一
        --lenght;
        return removeObj;
    }
  1. 插入操作及分析
 public void insert(int i, T t) {
        // 首先,先判度下标 i 是否合法
        if (i < 0 || i > this.lenght)
            throw new IndexOutOfBoundsException("Index: " + i + ", Size: " + this.lenght);

        //判断是否超出顺序表的容量
        if (this.lenght >= this.objects.length)
            throw new ArrayIndexOutOfBoundsException("length = " + this.lenght + " Capacity" + this.initCapacity);

        //把下标为i及其后的元素,往后移移一位
        for (int j = this.lenght - 1; j >= i; --j) {
            objects[j + 1] = objects[j];
        }
        //插入元素
        objects[i] = t;
        lenght++;
    }
  1. 查找元素操作及其分析
public int indexOf(E e) {
    //先判断 元素是否为空,可防止空指针的出现
    if (t == null) {
        //为空则,返回顺序表中空元素的下标
        for (int i = 0; i < this.lenght; i++)
            if (objects[i] == null)
                return i;
    } else {
        //不为空,则返回与之匹配的元素下标
        for (int i = 0; i < this.lenght; i++)
            if (t.equals(objects[i]))
                return i;
    }
    return -1;
    }
  1. SqList 完整源码
4. 链表的概念
  1. 定义:
  1. 存储结构定义:
  1. 链表的结点结构
2.9 节点类的结构图.png
  1. 单链表的表示
2.7 单链表存储示意图.png 2.8 带头结点单链表存储示意图.png
5. 链表的实现及分析
  1. 结点类
public class LNode<T> {
    //数据域
    public T data;
    //指针域
    public LNode<T> next;
    //...略
}
  1. 查找操作
//按序号查找
 public T get(int i) {
        //获取第一个节点元素
        LNode node = head.next;
        //计数器
        int pos = 0;
        //遍历节点,直到节点为空 或者 指向第 i 个节点退出循环
        while (node != null && pos < i) {
            node = node.next; //指向后继节点
            ++pos;//计数器加一
        }
        //判断是否找到节点
        if (node == null || pos > i)
            throw new RuntimeException("第 " + i + " 个元素不存在!");

        return (T) node.data;
    }
  
  
  //按元素值查找
   public int indexOf(T t) {
          //获取第一个节点元素
          LNode node = head.next;
          //计数器
          int pos = 0;
  
          //判断查询的值是否为空
          if (t == null) {
              //遍历节点,直到节点为空 或者 节点的数据域为空,退出循环
              while (node != null) {
                  if (node.data == null) {
                      return pos;
                  }
                  node = node.next; //指向后继节点
                  ++pos;//计数器加一
              }
          } else {
              //遍历节点,直到节点为空 或者 指向值为 t的 节点退出循环
              while (node != null) {
                  if (t.equals(node.data)) {
                      return pos;
                  }
                  node = node.next; //指向后继节点
                  ++pos;//计数器加一
              }
          }
          return -1;
      }
  1. 插入操作
2.10 单链表插入操作.png
//带头结点链表插入操作
    public void insert(int i, T t) {
            LNode p = head;
            int pos = -1;
            //1. 找到第 (i-1)个节点(位置 i 的前驱节点)
            while (p.next != null && pos < i - 1) {
                p = p.next;
                pos++;
            }
            //判断插入位置的合法性
            if (p == null || pos > i - 1)
                throw new RuntimeException("插入节点的位置不合法!");
    
            //2. 创建一个新的节点
            LNode newNode = new LNode(t);
            //3.1 新节点的后继指针指向 原先第 i个节点
            newNode.next = p.next;
            //3.2  第(i-1)节点 p 的后继指针指向新节点
            p.next = newNode;
        }
        
    
    //不带头结点
    public void insert(int i, T t) {
        LNode p = head;
        int pos = 0;
    
        while (p.next != null && pos < i - 1) {
            p = p.next;
            pos++;
        }
        //判断插入位置的合法性
        if (p == null || pos > i)
            throw new RuntimeException("插入节点的位置不合法!");

        //2. 创建一个新的节点
        LNode newNode = new LNode(t);
        if(i==0){
        //插入表头时
            newNode.next = head;
            head = newNode;
        }else{
             newNode.next = p.next;
              p.next = newNode;
        }
    }
  1. 删除操作
2.12单链表删除操作.png
 public T remove(int i) {
        LNode p = head;
        int pos = -1;
        //找到待删除节点的前驱节点
        while (p.next != null && pos < i - 1) {
            p = p.next;
            ++pos;
        }
        if (pos > i - 1 || p == null)
            throw new RuntimeException("删除节点的位置不合法!");
        //待删除节点
        LNode remove = p.next;
        //3. 第 (i-1) 节点的指针指向 (i+1)节点
        p.next = remove.next;
        return (T) remove.data;
    }
  1. 单链表的创建
2.13头部插入法示意图.png
 public void insertAtHead(T t) {
        //构建新插入的节点
        LNode newNode = new LNode(t);
        //新节点的后继指针指向头结点的头指针
        newNode.next = head.next;
        //头指针指向新节点
        head.next = newNode;
    }
2.14 尾部插入法示意图.png
public void insertTail(T t) {
    //获取到最后的节点
    LNode tail = this.head;
    while (tail.next != null) {
        tail = tail.next;
    }
    //构造新的节点
    LNode newNode = new LNode(t);
    //新节点指针指向 尾节点指针
    newNode.next = tail.next;
    //尾节点指针指向新节点
    tail.next = newNode;
}
  1. 单链表实现源码
6. 循环链表
2.18带头结点的循环链表存储示意图.png
  1. 实现循环链表的方式
  1. 循环链表尾指针方式实现源码
7. 双向链表
2.20带头结点的双向链表.png
  1. 结点类
public class DuLNode<E> {
    public E data;//数据域
    public DuLNode<E> prior;//前驱指针
    public DuLNode<E> next;//后驱指针
    public DuLNode() {
        this(null);
    }
    public DuLNode(E data) {
        this.data = data;
        this.prior = null;
        this.next = null;
    }
}
  1. 插入操作


    2.22双向链表插入.png
    public void insert(int i, E t) {
        //先判断索引是否合法
        if (i < 0 || i > length)
            throw new RuntimeException("插入元素的位置不合法! i=" + i);
        DuLNode<E> p = head;
        //下标
        int index = -1;
        //找到第i个元素
        while (p.next != null && index < i) {
            index++;
            p = p.next;
        }
        //创建一个新的结点
        DuLNode<E> newNode = new DuLNode<>(t);
        if (i == 0 || i == length) {
            newNode.prior = p;
            p.next = newNode;
        } else {
            //1. 第i个结点p的前驱结点的后继指向新结点
            p.prior.next = newNode;
            //2. 新结点的前驱指向第(i-1)个结点
            newNode.prior = p.prior;
            //3. 新结点的后驱指向第i个结点p
            newNode.next = p;
            //4. 第i个结点p的前驱指向新结点
            p.prior = newNode;
        }
        //长度加一
        length++;
    }
  1. 删除操作


    2.23双向链表删除.png
    public E remove(int i) {

        //先判断索引是否合法
        if (i < 0 || i > length - 1)
            throw new RuntimeException("删除元素不存在! i=" + i);

        DuLNode<E> p = head;
        //下标
        int index = -1;
        //找到第i个元素
        while (p.next != null && index < i) {
            index++;
            p = p.next;
        }

        DuLNode<E> remove = p;

        //1. 第(i-1)个结点的后驱指向 第 (i+1)个结点
        p.prior.next = p.next;
        //2. 第 (i+1)个结点的前驱指向 第(i-1)个结点
        p.next.prior = p.prior;

        //长度减一
        length--;
        return remove.data;
    }
  1. 双向链表完整源码
8. 链表与顺序表的比较
上一篇下一篇

猜你喜欢

热点阅读