阅读 165

数据结构-线程表

简介

线性表分为:顺序表,链表,栈和队列 结构上:顺序存储结构 & 链式存储结构

顺序表 & 顺序存储结构

实现:数组

特点:

  1. 存储线性表的数据元素的方式 = 一段地址连续的存储单元
  2. 具备:起始位置、数组长度(最大存储容量) & 线性表长度(当前长度)

操作:
顺序存储结构的操作包括:插入 & 删除

链式存储结构

实现:链表
特点:链式存储结构的数据元素的方式 = 一段地址不连续的存储单元
区分:单链表、双向链表、循环链表、静态链表

单链表

特点:链式存取的数据结构,单链表中的数据是以结点的形式存在,每一个结点是由数据元素和下一个结点的存储的位置组成。每个结点只有1个指针域
结点

单链表实现

public class UnidirectionalLinkedList<T> {

    /**
     * 设置结点结构
     */
    // a. 结点结构
    private class Node<T>{
        private T data;
        private Node<T> next ;
        public Node(T data){
            this.data = data;
        }
    }

    // b. 头结点
    private Node<T> first;
    // c. 当前结点
    private Node<T> currentNode;
    // d. 链表长度
    private int size;

    /**
     * 构造函数
     * 作用:初始化结点
     */
    public UnidirectionalLinkedList(){
        currentNode = first = null;
        size = 0;
    }

    /**
     * 1. 添加结点
     * 内容:在头 / 尾 添加结点 & 在特定位置插入结点
     */

    // a. 在链表头部加入1个结点
    // 即,把新加入的结点设置为第一结点
    public void addFirstNode(T data){

        // 1. 将需添加的内容封装成结点
        Node<T> newNode = new Node<T>(data);
        // 2. 将新添加结点的指针域指向旧第1个结点
        newNode.next = first;
        // 3. 将新添加结点设置为第1个结点
        first = newNode;
        // 4. 链表长度+1
        size++;
    }

    // b. 在链表尾部加入1个结点
    // 即,把新加入的结点设置为最后结点
    public void addNode(T data){
        // 1. 检查当前链表是否为空
        if (isEmpty()){
            addFirstNode(data);
            return;
        }
        // 2. 把当前指针定位到最后一个结点
        locateNode(size-1);
        // 3. 将需添加的内容封装成结点
        currentNode.next = new Node<T>(data);
        // 4. 链表长度+1
        size++;
    }

    // c. 在链表中插入结点
    public T insertNode(int index, T data) {
        // 1. 检查当前链表是否为空
        if (isEmpty()){
            addFirstNode(data);
            return null;
        }

        // 2. 把当前指针定位到需插入的结点位置
        locateNode(index);
        // 3. 将需添加的内容封装成结点
        Node<T> insertNode = new Node<T>(data);
        // 4. 把需插入结点位置的下1个结点 赋给 插入的结点
        insertNode.next = currentNode.next;
        // 5. 把插入结点 赋给 需插入的结点的位置
        currentNode.next = insertNode;
        // 6. 链表长度+1
        size++;
        // 7. 返回插入结点的数据
        return insertNode.data;
    }


    /**
     * 2. 删除结点
     * 内容:删除第1个结点 & 删除特定位置的结点
     */
    // a. 删除第1个结点,并返回该结点数据
    public T removeFirstNode()  {
        // 1. 检查当前链表第一个结点是否为空
        if (first == null){
            try {
                throw new Exception("链表为空!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 2. 获取被删除结点的数据
        T temp = first.data;
        // 3. 将第2个结点设置为第1个结点
        first = first.next;
        // 4. 链表长度减1
        size--;

        // 5. 返回被删除结点的数据
        return temp;
    }


    // b. 删除特定位置的结点,并将里面的数据返回
    public T removeNode(int index)  {
        // 1. 检查当前链表是否为空
        if (isEmpty()){
            try {
                throw new Exception("链表为空!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 2. 把当前指针(currentNode)定位到 需删除结点(index)的前1个结点
        locateNode(index-1);
        // 3. 获取被删除结点的数据
        T temp = currentNode.next.data;
        // 4. 将需删除结点(index)的前1个结点 的下1个结点 设置为 需删除结点(index)的下1个结点
        currentNode.next = currentNode.next.next;
        // 5. 链表长度减1
        size--;
        // 6. 返回被删除结点的数据
        return temp;
    }

    /**
     * 3. 获取特定位置的结点
     * 内容:将当前指针(currentNode)定位到所需结点位置、根据索引位置获取结点数据
     */

    // a. 将当前指针(currentNode)定位到所需结点位置
    private void locateNode(int index){
        // 1. 判断指针是否越界
        if (index <0 && index >size){
            try {
                throw new IndexOutOfBoundsException("参数越界!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        int i = 0;
        // 2. 通过遍历链表,寻找索引index所指结点
        for(currentNode = first; currentNode.next != null && i < index; i++){
            currentNode = currentNode.next;
        }
    }

    // b. 根据索引位置获取结点数据
    public T getNode(int index)  {
        // 1. 判断链表是否为空
        if (isEmpty()){
            try {
                throw new Exception("链表为空!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 2. 把当前指针(currentNode)定位到 所需索引位置(index)
        locateNode(index);
        // 3. 返回当前指针的数据,即所需索引位置的数据
        return currentNode.data;
    }

    /**
     * 检查当前链表是否为空
     */
    public boolean isEmpty(){
        if (size == 0){
            return true;
        }else {
            return false;
        }
    }


    public static void main(String[] args){
        // 1. 创建链表 & 加入结点数据
        UnidirectionalLinkedList<Integer> list = new UnidirectionalLinkedList<Integer>();
        list.addNode(1);
        list.addNode(2);
        list.addNode(3);
        list.addNode(4);
        list.addNode(5);

        // 2. 输出当前链表数据
        System.out.println("链表数据如下:");
        for (int i = 0; i < list.size;i++){
            
            try {

                System.out.print(list.getNode(i)+" ");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("-----------------------");


        // 3. 获得某个位置结点的数据
        System.out.println("位置3的数据是:" + list.getNode(3));


        System.out.println("-----------------------");


        // 4. 插入结点:在位置4插入,数据 = 66
        System.out.println("在位置4插入的data:"+list.insertNode(3,66));
        System.out.println("插入后:");
        for (int i = 0; i < list.size;i++){
            try {
                System.out.print(list.getNode(i)+" ");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        System.out.println("-----------------------");

        // 5. 删除结点
        System.out.println("删除index为3的data:"+list.removeNode(3));
        System.out.println("删除后:");
        for (int i = 0; i < list.size;i++){
            try {
                System.out.print(list.getNode(i)+" ");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}

复制代码

循环列表,

将单链表的终端结点的指针指向头结点、使得单链表头尾相接、形成1个环

双向链表

特点:每个结点有2个指针域:1指向后驱结点元素、2指向前驱结点元素

package com.struct.linklist;
 
 
/**
 * @描述         双向链表
 * @项目名称      Java_DataStruct
 * @包名         com.struct.linklist
 * @类名         LinkList
 * @author      chenlin
 * @date        2010年6月26日 上午8:00:28
 * @version     1.0 
 */
 
public class DoubleLinkList {
 
    //头
    private Node first;
    //尾
    private Node last;
 
    public DoubleLinkList(){
        first = null;
        last = null;
    }
 
    /**
     * 插入数据
     * @param value
     */
    public void insertFirst(long value){
        Node newNode = new Node(value);
        if (first == null) {
            last = newNode;
        }else {
            first.previous = newNode;
            //把first节点往下移动
            newNode.next = first;
        }
        //把插入的节点作为新的节点
        first = newNode; 
    }
 
    /**
     * 插入数据
     * @param value
     */
    public void insertLast(long value){
        Node newNode = new Node(value);
        if (first == null) {
            first = newNode;
        }else {
            last.next = newNode;
            //first.previous = newNode;
            newNode.previous = last;
        }
        //把最后个节点设置为最新的节点
        last = newNode;
    }
 
    public boolean isEmpty(){
        return first == null;
    }
 
    /**
     * 删除头节点时要去除两个指针,一个指向下个的next ,一个是next的previous指向前面的
     * 
     * @param value
     * @return
     */
    public Node deleteFirst(){
        if (first == null) {
            throw new RuntimeException("链表数据不存在");
        }
        Node temp = first;
        if (first.next == null) {
            last = null;
        }else {
            first.next.previous = null;
        }
        first = temp.next;
        return temp;
    }
 
    /**
     * 删除头节点时要去除两个指针,一个指向下个的next ,一个是next的previous指向前面的
     * 
     * @param value
     * @return
     */
    public Node deleteLast(){
        if (first == null) {
            throw new RuntimeException("链表数据不存在");
        }
 
        Node temp = last;
        if (first.next == null) {
            last = null;
            //把第一个删除
            first = null;
        }else {
            last.previous.next = null;
        }
        last = temp.previous;
        return temp;
    }
 
    /**
     * 删除
     * @param key
     * @return
     */
    public Node deleteByKey(long key){
        Node current = first;
        while(current.data != key){
            if (current.next == null) {
                System.out.println("没找到节点");
                return null;
            }
            current = current.next;
        }
        if (current == first) {
            //return deleteFirst();
            //指向下个就表示删除第一个
            first = first.next;
        }else {
            current.previous.next = current.next;
        }
        return current;
    }
 
    /**
     * 显示所有的数据
     */
    public void display(){
        if (first == null) {
            //throw new RuntimeException("链表数据不存在");
            return;
        }
        Node current = first;
        while(current != null){
            current.display();
            current = current.next;
        }
        System.out.println("---------------");
    }
 
    /**
     * 查找节点1
     * @param value
     * @return
     */
    public Node findByValue(long value){
        Node current = first;
        while(current != null){
            if (current.data != value) {
                current = current.next;
            }else {
                break;
            }
        }
        if (current == null) {
            System.out.println("没找到");
            return null;
        }
        return current;
    }
 
    /**
     * 查找节点2
     * 
     * @param key
     * @return
     */
    public Node findByKey(long key) {
        Node current = first;
        while (current.data != key) {
            if (current.next == null) {
                System.out.println("没找到");
                return null;
            }
            current = current.next;
        }
        return current;
    }
 
    /**
     * 根据索引查找对应的值
     * @param position
     * @return
     */
    public Node findByPosition(int position){
        Node current = first;
        //为什么是position - 1,因为要使用遍历,让current指向下一个, 所以position - 1的下个node就是要找的值
        for (int i = 0; i < position - 1 ; i++) {
            current  = current.next;
        }
        return current;
    }
 
 
    public static void main(String[] args) {
        DoubleLinkList linkList = new DoubleLinkList();
        linkList.insertFirst(21);
        linkList.insertFirst(22);
        linkList.insertFirst(23);
        linkList.insertLast(24);
        linkList.insertLast(25);
        linkList.insertLast(26);
        linkList.insertLast(27);
 
        linkList.display();
 
        System.out.println("---查找-------------------------------------");
 
        linkList.findByKey(25).display();
 
        System.out.println("--删除first-------------------------------------");
 
        //linkList.deleteFirst().display();
        ///linkList.deleteFirst().display();
        //linkList.deleteFirst().display();
        //linkList.deleteFirst().display();
 
        System.out.println("-删除指定值---------------------------------------");
        linkList.deleteByKey(27).display();
        linkList.deleteByKey(21).display();
 
        System.out.println("----------------------------------------");
        linkList.display();
 
 
    }
}
复制代码

静态链表

用数组描述的链表,即称为静态链表。 特点:这种存储结构,仍需要预先分配一个较大的空间,但在作为线性表的插入和删除操作时不需移动元素,仅需修改指针,故仍具有链式存储结构的主要优点。

//实现
/**
 * @DESCRIPTION TODO
 * @DATE 2019年3月23日 下午9:08:11
 * @AUTHOR tmooming
 */
public class SNode<T> {
    public T data;
    private int cursor;

    public SNode() {

    }

    public SNode(T data, int cursor) {
        this.data = data;
        this.cursor = cursor;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public int getCursor() {
        return cursor;
    }

    public void setCursor(int cursor) {
        this.cursor = cursor;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append(getData());
        sb.append(" ");
        sb.append(getCursor() + " ");
        return sb.toString();

    }
}

/**
 * @DESCRIPTION TODO
 * @DATE 2019年3月23日 下午9:08:23
 * @AUTHOR tmooming
 */
public class SList<T> {
    SNode<T>[] node;
    private static final int MAX_SIZE = 15;
    private int length;

    public SList() {
        node = new SNode[MAX_SIZE];
        for (int i = 0; i < MAX_SIZE - 1; i++) {
            node[i] = new SNode<T>(null, i + 1);
        }
        node[MAX_SIZE - 1] = new SNode<>(null, 0);
        this.length = 0;
    }

    // 实际数组长度
    public int Length() {
        return length;
    }

    // 判断使用数组是否为空
    public boolean isEmpty() {
        return length == 0;
    }

    // 判断备用链表是否为空
    public boolean isFull() {
        return length == MAX_SIZE;
    }

    // 插入一个节点
    public boolean addTo(T data, int index) {
        if (isFull() || index > MAX_SIZE || index < -1 || data == null)
            return false;
        if (index == 0) {
            insert(data);
            return true;
        }
        if (index > Length()) {
            index = Length();
        }
        // 获取第一个使用节点的下标
        int firstUse = node[MAX_SIZE - 1].getCursor();
        // 获取备用数组第一个节点的下标
        int firstNull = node[0].getCursor();
        for (int i = 1; i < index; i++) {
            firstUse = node[firstUse].getCursor();
        }
        // 获取目标节点的后续节点
        int nextUse = node[firstUse].getCursor();
        int nextNull = node[firstNull].getCursor();
        node[0].setCursor(nextNull);
        node[firstUse].setCursor(firstNull);
        node[firstNull].setCursor(nextUse);
        node[firstNull].setData(data);
        length++;
        return true;

    }

    public void insert(T data) {
        int t = node[MAX_SIZE - 1].getCursor();
        int firstNull = node[0].getCursor();
        node[MAX_SIZE - 1].setCursor(firstNull);
        node[0].setCursor(node[firstNull].getCursor());
        node[firstNull].setCursor(t);
        node[firstNull].setData(data);
        length++;
    }

    public void print() {
        int first = node[MAX_SIZE - 1].getCursor();
        System.out.println("链表:");
        for (int i = first; i != 0;) {
            System.out.print(node[i].getData() + " ");
            i = node[i].getCursor();
        }

    }

    // 删除指定节点
    public boolean delete(T data) {
        if (isEmpty()) {
            return false;
        }
        int temp = MAX_SIZE - 1;
        while (temp != 0) {
            if (node[node[temp].getCursor()].getData() == data) {
                int p = node[temp].getCursor();
                node[temp].setCursor(node[p].getCursor());
                node[p].setCursor(node[0].getCursor());
                node[0].setCursor(p);
                node[p].setData(null);
                length--;
                return true;
            }
            temp = node[temp].getCursor();
        }
        return false;
    }

    // 删除所有节点
    public boolean deleteAll() {
        if (isEmpty()) {
            return true;
        }
        for (int i = 0; i < MAX_SIZE - 1; i++) {
            node[i].setCursor(i + 1);
            node[i].setData(null);
        }
        node[MAX_SIZE - 1].setCursor(0);
        node[MAX_SIZE - 1].setData(null);
        length = 0;
        return true;
    }

    public void printAll() {

        System.out.println("链表:");
        for (int i = 0; i < MAX_SIZE; i++) {
            System.out.print("[" + i + " " + node[i].getData() + " " + node[i].getCursor() + "]");
            if (i % 5 == 0 && i != 0) {
                System.out.println();
            }

        }

    }

    public static void main(String[] args) {
        SList<String> list = new SList<String>();
        list.insert("赵");
        list.insert("钱");
        list.insert("李");
        // list.printAll();
        // list.addTo("孙", 5);
        list.deleteAll();
        System.out.println(list.Length());
        list.printAll();

    }
}

复制代码
文章分类
Android
文章标签