数据结构基础(一)线性表

大学快要结束了,打算抓紧最后一段时间回顾下数据结构的知识,今天是第一篇,希望自己能够坚持完。

  1. 定义
    线性表是n个数据元素的有限序列。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。
  2. 分类
    • 顺序表:即用数组实现的线性表。逻辑上相邻的元素物理地址也相邻,访问容易,插入和删除元素麻烦
    • 链表:用指针连接元素,逻辑上相邻的元素物理地址不一定相邻。访问麻烦,插入和删除容易。
      又可分为:
      • 线性链表:除终节点外,每个节点都有指向下一个元素的指针
      • 循环链表:最后一个节点指向头节点
      • 双向链表:每个节点都有指向前个节点和后个节点的指针
  3. Demo

顺序表Demo

//模仿ArrayList的顺序表
public class Arraylist {
    private Object[] elementDate=null;
    private int capacity;
    private int current;
    //默认初始化容器大小为5
    public Arraylist(){
        this.current=0;
        this.capacity=5;
        this.elementDate=new Object[capacity];
    }
    //按所给容量初始化容器
    public Arraylist(int capacity){
        this.current=0;
        this.capacity=capacity;
        this.elementDate=new Object[capacity];
    }
    //获得指定索引的元素
    public Object get(int index) {
        if(index>=0&&index<capacity)
            return elementDate[index];
        return null;
    }
    //添加元素
    public void add(Object element) {
        //每次插入都要检查容器大小
        ensureCapacity();
        elementDate[current++]=element;
    }
    //在指定下标插入元素
    public void add(int index,Object element) {
        //每次插入都要检查容器大小
        ensureCapacity();
        //确定下标合法
        if(index>current||index<0)
            throw new IndexOutOfBoundsException();

        for (int i = current; i >index; i--) {
            elementDate[i]=elementDate[i-1];
        }
        elementDate[index]=element;
        current++;
    }
    //删除指定位置的元素
    public void delete(int index) {
        if(index>=current||index<0)
             throw new IndexOutOfBoundsException();
//      //也可直接使用函数复制数组
//      int length=current-index;
//      System.arraycopy(elementDate, index+1, elementDate, index, length);
        for (int i = index; i < current-1; i++) {
            elementDate[i]=elementDate[i+1];
        }
        elementDate[--current]=null;
    }
    //确保增加元素后的容器不会溢出
    public void ensureCapacity() {
        if(current+1>=capacity){
            capacity+=5;
            Object[] newElementDate=new Object[capacity];
//          elementDate=Arrays.copyOf(elementDate, capacity); //也直接使用函数
            for (int i = 0; i < elementDate.length; i++) {
                newElementDate[i]=elementDate[i];
            }
            elementDate=newElementDate;
        }
    }
    //遍历出容器内的元素
    public void dolist() {
        for (int i = 0; i < current; i++) {
            System.out.print(elementDate[i]+" ");
        }
        System.out.println("["+capacity+"]");
    }

    public static void main(String[] args) {
        Arraylist list=new Arraylist();
        System.out.println("添加4个元素");
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.dolist();
        System.out.println("插入一个元素");
        list.add(1, 1.5);
        list.dolist();
        System.out.println("删除一个元素");
        list.delete(1);
        list.dolist();
        System.out.println("获取指定4位置元素");
        System.out.println(list.get(4));
        System.out.println("再加几个元素测试溢出");
        list.add(5);
        list.add(6);
        list.dolist();
    }
}/*output
添加4个元素
1 2 3 4 [5]
插入一个元素
1 1.5 2 3 4 [10]
删除一个元素
1 2 3 4 [10]
获取指定4位置元素
null
再加几个元素测试溢出
1 2 3 4 5 6 [10]**/

单链表Demo

//模仿LinkedList的单链表
public class Linkedlist {
    // 链表的第一个节点
    private Node first;
    // 链表的最后一个节点
    private Node last;
    // 链表的长度
    private int size = 0;

    /**
     * 链表节点
     */
    private static class Node {
        // Node pre; //若为双向链表加上,实际LinkedList就是双向链表结构
        Object item;
        Node next;

        public Node(Object item, Node next) {
            this.item = item;
            this.next = next;
        }
    }

    /**
     * 空构造,第一次添加元素时才初始化first,last
     */
    public Linkedlist() {
        // TODO Auto-generated constructor stub
    }

    /**
     * 添加一个元素
     * 
     * @param element
     */
    public void add(Object element) {
        Node newNode = new Node(element, null);
        Node l = last;
        last = newNode;
        // 如果此时为空链表,则初始化first,last
        if (first == null)
            first = last;
        else
            l.next = newNode;

        size++;
    }

    /**
     * 增加元素到指定的下标位置
     * 
     * @param index
     * @param element
     */
    public void add(int index, Object element) {
        // 检验索引是否正确
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException();
        // 判断是否插在last节点后
        if (index == size) {
            add(element);
        }
        // 判断是否插在first节点上
        else if (index == 0) {
            Node newNode = new Node(element, first);
            first = newNode;
            size++;
        } else {
            Node preNode = getNode(index - 1);
            Node nextNode = preNode.next;
            Node newNode = new Node(element, nextNode);
            preNode.next = newNode;
            size++;
        }
    }

    /**
     * 删除指定索引处的节点元素
     * 
     * @param index
     */
    public void delete(int index) {
        // 检验索引是否正确
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException();

        // 判断是否删除first节点
        if (index == 0) {
            first = first.next;
        } else {
            Node preNode = getNode(index - 1);
            Node delNode = preNode.next;
            Node nextNode = delNode.next;
            preNode.next = nextNode;
            // 判断是否删除last节点
            if (index == size-1) 
                last=preNode;
            // 方便垃圾回收机制回收
            delNode.item = null;
            delNode.next = null;
        }
        size--;
    }

    /**
     * 获取指定下标的节点
     * 
     * @param index
     * @return
     */
    public Node getNode(int index) {
        // 检验索引是否正确
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException();
        // 从头节点开始寻找,如果为双向链表,可以判断index挨头和尾哪边近,然后从哪边开始查找
        Node node = first;
        for (int i = 0; i < index; i++) {
            node = node.next;
        }
        return node;
    }

    public Object get(int index) {
        return getNode(index).item;
    }

    /**
     * 遍历输出所有节点元素
     */
    public void dolist() {
        Node node = first;
        for (int i = 0; i < size; i++) {
            System.out.print(node.item + " ");
            node = node.next;
        }
        System.out.println("[" + size + "]");
    }

    public static void main(String[] args) {
        Linkedlist list = new Linkedlist();
        System.out.println("添加4个元素");
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.dolist();
        System.out.println("插入一个元素");
        list.add(4, 1.5);
        list.dolist();
        System.out.println("删除一个元素");
        list.delete(0);
        list.dolist();
        System.out.println("获取指定3位置元素");
        System.out.println(list.get(3));
    }
}/*output
添加4个元素
1 2 3 4 [4]
插入一个元素
1 2 3 4 1.5 [5]
删除一个元素
2 3 4 1.5 [4]
获取指定3位置元素
1.5**/

双向链表和双向循环链表就不举例了,只是在单链表的基础上Node加了一些改动。实际上java的LinkedList里面采用的就说双向链表。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值