算法自学--第二天--手写顺序表,链表

线性表:

概念:零个或多个数据元素的有限集合;

线性表必须是一个序列,,也就是说元素之间是有顺序的,如果元素存在多个,则第一个元素无前驱,最后一个元素无后继,其余每一个元素都有各自唯一的前驱和后继;
在这里插入图片描述

当线性表内的元素为空时,这个表就是一个空表;
下标的位置是元素在线性表的位序;

线性表的存储结构:

用一段连续的存储单元依次存储线性表的数据元素;
在任意时刻。线性表的长度应该小于等于数组的长度;

地址计算:

第i个数据元素的ai的存储位置可以由a1推导:
LOC(ai) = LOC(a1) + (i-1)*C

线性表插入思路:

1.如果插入的位置不合适(插入的位置不能小于0,最大位置不能超过数组的长度),应该抛出异常;
2.线性表的长度要小于等于数组的长度;
3.从最后一个元素向前遍历,依次后移一位;
4.将要插入的元素插入到对应的位置;

Java实现(我直接正着后移了):

package com.lzl.linerTable;

import java.util.Arrays;

/**
 * 向数组内插入元素,时间复杂度 O(n) 空间复杂度 O(1)
 *
 */
public class InsertArray {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,5,7,4,6,8,9,12,34,56};
        int num = 33;
        int[] arr1 = new int[arr.length+1];
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = arr[i];
        }
        for (int i = 2; i < arr1.length-1 ; i++) {
            if (i == 2){
                arr1[i+1] = arr1[i];
                arr1[i] = num;
            }else {
                arr1[i + 1] = arr[i];
            }
        }
        System.out.println(Arrays.toString(arr1));
    }
}

删除算法的思路:

1.如果删除的位置不合理,抛出异常
2.取出删除元素;
3.从删除位置开始遍历到最后一个位置,分别将它们向前移一位
4.表长度-1
Java实现数组删除:

 /**
     * 数组删除算法,时间复杂度: O(n),空间复杂度:O(1)
     * @param arr   
     * @param index
     * @return
     */
    public static int deleteArr(int[] arr,int index){
        int result = 0;
        if (index<0 || index>arr.length){
            return -1;
        }
        result = arr[index];
        for (int i = index ; i < arr.length - 1; i++) {
            arr[i] = arr[i+1];
        }
        arr = new int[arr.length-1];
        return result;
    }

顺序表的优势:

无需为表示表中的逻辑关系额外增加存储空间;
可以快速的取表中的某一位置的元素

缺点:

插入和删除操作需要大量的移动元素;
当线性表变化较大时,难以确定其容量;
会造成空间的碎片化

线性表的链式存储结构:

概念:用一组任意的存储结构单元存储存储线性表的数据元素;

链式结构的每一个元素称为节点,它存储两个域;数据存储的域称为数据域,将存储后继节点的位置的域称为指针域;
只包含一个指针域的链表称为单链表;
在这里插入图片描述

头指针和尾指针:

我们把一个节点的存储位置称为头指针,每一个的后继节点的位置就是上一个节点的指针;
最后一个节点的指针通常为空
有时会在第一个节点前创建一个头结点节点,头结点的数据域可以没有数据,也可以存储链表的长度等信息,头指针指向存储区的第一个节点;
在这里插入图片描述

Java实现一个单链表:

创建一个节点:

package com.lzl.linerTable;

public class Node<E> {
    //节点数据
    public E data;
    //节点的后继
    public Node<E> nextNode;

    public Node(E data) {
        this.data = data;
    }

}

创建一个链表:

public class TestLinkedList<E>  {
    //数组长度
    private int size = 0;
    //下标位置
    private int index = 0;
    //头结点
    private Node<E> head;
    //尾结点
    private Node<E> end;

    public TestLinkedList() {
        this.head = null;
    }
}

增加节点:

/**
 * 添加元素
 * 算法思路:设置一个boolean值记录运行结果;
 * 1. 创建一个新的节点将data通过构造方法注入;
 * 2. 如果尾结点 是空的,说明链表内没有节点,这个节点就是唯一节点,将下标位置+1;
 * 3. 如果有节点,将这个节点加到尾结点的后面,并把这个节点作为新的尾结点,将下标+1;
 * 4. 将链表的长度+1,将下标指针指回0位置;
 * @param data
 * @return
 */
public boolean add(E data){
    boolean flag = false;
    Node<E> node = new Node<>(data);
    if (end == null){
        head = end = node;
        index++;
        flag = true;
    }else {
        end.nextNode = node;
        end = node;
        index++;
        flag = true;
    }
    size++;
    index = 0;
    return flag;
}

获取节点数据:

/**
 * 获取下标节点数据
 * 1. 首先判断请求的下标符不符合链表长度,如果不符合就抛出异常;
 * 2. 定义一个当前节点currentNode,再定义一个当前节点的上一个节点preNode;
 * 3. 如果当前的index和数组下标的index不相等,就执行while循环,将当前节点指向后继节点
 * @param index
 * @return
 */
public E get(int index){
    if (this.size == 0){
        return null;
    }
    if (index > this.size || index < 0){
        throw new ArrayIndexOutOfBoundsException();
    }
    Node<E> currentNode = head;
    while (this.index != index ){
        currentNode = currentNode.nextNode;
        this.index ++;
    }
    this.index = 0;
    return currentNode.data;
}

删除节点:

/**
 * 删除数据元素
 * 1. 先判断元素是否合法;
 * 2. 判断是否为头结点,如果为头结点,就直接将头结点变成头结点的下一个节点;
 * 3. 判断当前节点是否为空,不为空进入循环,判断如果等于index,则将前一个节点的后继指向下一个节点的后继,链表长度-1;
 * 4. 如果不是index节点,就将前一个节点指向当前节点,当前节点指向后一个节点,让位置+1;
 * @param index
 * @return
 */
public boolean delete(int index){
    boolean flag = false;
    if (index > this.size || index < 0){
        throw new ArrayIndexOutOfBoundsException();
    }
    if (head == null){
        return flag;
    }
    if (index == 1){
        head = head.nextNode;
        size --;
        return true;
    }

    Node<E> currentNode = head.nextNode;
    Node<E> preNode = head;
    int i = 2;
    while (currentNode != null){
        if (i == index){
            preNode.nextNode = currentNode.nextNode;
            size --;
            break;
        }else {
            preNode = currentNode;
            currentNode = currentNode.nextNode;
            i++;
        }
    }

    return flag;
}

打印链表:

/**
 * 打印链表数据元素
 * 1. 创建一个节点作为当前节点;
 * 2. 判断当前节点是否为空,不为空就打印节点内的数据,将数据进行拼接;
 */
public void printList(){
    Node<E> currentNode = head;
    System.out.print("[ ");
    while (currentNode != null){
        if (currentNode.nextNode != null) {
            System.out.print(currentNode.data + ",");
        }else {
            System.out.print(currentNode.data );
        }
        currentNode = currentNode.nextNode;
    }
    System.out.println(" ] ");
}

返回链表长度:

/**
 * 返回当前链表长度
 * @return
 */
public int size(){
    return this.size;
}

测试:

public static void main(String[] args) {
    TestLinkedList<Integer> linkedList = new TestLinkedList<Integer>();
    linkedList.add(1);
    linkedList.add(1);
    linkedList.add(1);
    linkedList.add(2);
    linkedList.add(3);
    linkedList.add(55);
    System.out.println(linkedList.size);
    Integer integer = linkedList.get(4);
    System.out.println(integer);
    linkedList.delete(1);
    linkedList.printList();

}

结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

so_defficult

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值