美文网首页
动态链表与静态链表

动态链表与静态链表

作者: cccccttttyyy | 来源:发表于2018-07-25 21:51 被阅读0次

动态链表与静态链表

1. 静态链表

静态链表概述

从他的意义上讲,静态链表像是对没有指针的语言缺陷而产生这么一个补救方法。每个包含了数据域与指针域。相对于C中的指针,这里的指针指的是数组的下标(也称静态指针故将此链表称为静态链表)。

从结构上来说,静态链表分为两个部分,一部分是已存有数据的线性表,另一部分是空闲节点组成的链表,添加新元素不再是申请空间,而是从空闲链表中申请。当下一个指针是-1时代表链表已满。

静态链表优缺点

他综合了顺序表与链表的优点与缺点。

  1. 空间分配上,静态链表与顺序表一致,预先分配较大空间,但不需要再频繁的开辟回收资源,整体上占用的空间是连续的,不够灵活。
  2. 数据操作上,又结合了链表的的优势,插入删除效率较高。查询没有顺序表直接。
    个人觉得用途不大。

静态链表的实现

研读了一些代码后,最终copy了一份代码,源自:https://blog.csdn.net/u013293125/article/details/52947005

/**
 * 因为静态链表实质上是一维数组的存储方式,所以它在物理位置上的存储
 * 是顺序的,但它是用游标来指向下一个数据的,所以根据它的下标来获取数据
 * 和按照游标的指向来获取数据是不同的,这里设置该链表的头结点为空
 * @author Administrator
 *
 */
public class StaticLinkList {

    private Element[] linkList = null; 
    private int DEFAULT_SIZE = 4;//默认存储大小
    private int currentFree = 0;//指向当前空闲位置
    private int size = 1;
    class Element{
        int data;
        int cur;
    }
    /**
     * 静态链表的长度
     * @return
     */
    public int length(){
        return size-1;
    }
    /**
     * 静态链表的初始化
     */
    public StaticLinkList(){
        linkList = new Element[DEFAULT_SIZE];
        for (int i = 0; i < linkList.length; i++) {
            linkList[i] = new Element();
            linkList[i].data = -1;
            linkList[i].cur = i+1;
        }
        //当前空闲节点从1开始,因为第0个节点设置成了头结点,设置为空,不
        //存储数据
        currentFree = 1;
    }
    /**
     * 给链表添加数据,每当链表满了就给链表添加额外的空间
     * @param data
     */
    public void add(int data){
        if(size>=linkList.length){
           addLinkSpace();
        }//链表已满,给链表添加空间
            linkList[currentFree].data = data;
            currentFree = linkList[currentFree].cur;
            size++;
    }
    /**
     * 得到索引指定的数据
     * @param index
     * @return
     */
    public int get(int index){
        if(index>size-1&&index<0)
            throw new IndexOutOfBoundsException("数组越界,索引不合法");
        else{
            //这里index+1也是因为多了一个空的头节点
            return linkList[index+1].data;//仅仅是索引,并不一定是在链表中的位置
        }
    }
    /**
     * 删除指定位置的节点
     * @param index
     */
    public void delete(int index){

        index = index+1;
        if(index<1||index>=size){
            System.out.println("超出链表长度");
        }else if(index == size-1){//删除最后一个数据
            size--;
            linkList = (Element[]) getTrueIndex(linkList,size);
        }else{
            int i = 0;
            while(index!=linkList[i].cur){//i位置是要删除的数据的前一个索引值
                i++;
            }
            int j = 0;
            while(currentFree!=linkList[j].cur){//j是标记当前空闲链表头的前一项,为了将删除的节点加入到空闲链表中
                j++;
            }
            linkList[i].cur = linkList[index].cur;
            linkList[j].cur = index;
            linkList[index].cur = currentFree;
            currentFree = index;
            size--;
            linkList = (Element[]) getTrueIndex(linkList,size);
        }
    }
    /**
     * 增加链表空间
     */
    public void addLinkSpace(){
        DEFAULT_SIZE+=8;
        Element[] link = linkList;
        linkList = new Element[DEFAULT_SIZE];
        System.arraycopy(link, 0, linkList, 0, link.length);
        for (int i = link.length; i < DEFAULT_SIZE; i++) {
            linkList[i] = new Element();
            linkList[i].data = -1;
            linkList[i].cur = i+1;
        }
        currentFree = link.length;
    }

    /**
     * 根据指定的位置插入数据
     * @param index
     * @param data
     */
    public void insert(int index,int data){
        //这里加1的原因是因为链表的第0位为空节点,这里设置的头节点为空
        index = index + 1;
        if(size<linkList.length){
            if(index>size&&index<0)
                System.out.println("数组越界,超出数组长度");
            else if(index == size){
                linkList[currentFree].data = data;
                currentFree = linkList[currentFree].cur;
                size++;
            }else{
                /******未按逻辑顺序排序而插入数据的写法,因为未排序,则当前索引的上个节点的索引不一定是当前索引减1****/
                int i = 0;
                while(index!=linkList[i].cur){
                    i++;
                }
                int j = 0;
                while(currentFree!=linkList[j].cur){
                    j++;
                }
                linkList[i].cur = currentFree;
                linkList[j].cur = linkList[currentFree].cur;
                linkList[currentFree].data = data;
                linkList[currentFree].cur = index;
                currentFree = linkList[j].cur;
                size++;
                //每次插入后将链表按逻辑顺序重新排序,是为了方便输出查看。
                linkList = (Element[]) getTrueIndex(linkList,size);
            }
        }else{
            addLinkSpace();
            insert(index, data);
        }
    }
    /**
     * 按照逻辑顺序重新排列
     * @param link 
     * @return
     */
    public Object getTrueIndex(Element[] link,int size){
        Element[] linkList1 = new Element[linkList.length];
        int k =0;
        for (int i = 0; i < linkList.length; i++) {
            linkList1[i] = new Element();
            linkList1[i].data = link[k].data;
            k = link[k].cur;
            linkList1[i].cur = i+1;
        }
        //插入时,currentFree肯定是最后一个了,但删除后,currentFree就不一定是最后一位了
        currentFree = size;
        return linkList1;
    }
}

2. 动态链表

即上节说的链表。由于c具有指针,一般书上都用c实现。他不受初始分配空间限制,占用空间比较灵活,需要一个结点,就申请一个节点。
再copy一份java代码,源自:https://www.cnblogs.com/Y-oung/p/8886142.html

import java.util.Stack;
public class LinkedListOnePoint {
    private Node head;  //头结点
    private int size;  //链表长度,即链表中结点数量
    
    public LinkedListOnePoint(){
        head = null;
        size = 0;
    }
    
    //私有内部类,代表链表每个结点
    private class Node{
        private Object data;  //链表结点的值
        private Node next;  //指向的下一个结点
        public Node(Object data){
            this.data = data;
        }
    }
    
    //判断链表是否为空
    public boolean isEmpty(){
        return size==0?true:false;
    }
    
    //返回链表长度
    public int size(){
        return size;
    }
    
    //查看链表头结点,不移除
    public Object headNode(){
        if(size == 0) return null;
        return head.data;
    }
    
    //在链表表头插入一个结点(入栈)
    public void insertInHead(Object obj){
        Node newNode = new Node(obj);
        if(size == 0){
            head = newNode;
        }else{
            newNode.next = head;
            head = newNode;
        }
        size++;
    }
    
    //删除链表表头结点(出栈)
    public Object deleteHeadNode(){
        if(size == 0) return null;
        Object obj = head.data;
        if(head.next == null){
            head = null;  //只有一个结点
        }else{
            head = head.next;
        }
        size--;
        return obj;
    }
    
    //链表查找:判断链表中是否包含某个元素
    public boolean containObject(Object obj){
        if(size == 0) return false;
        Node n = head;
        while(n != null){
            if(n.data == obj) return true;
            else n = n.next;
        }
        return false;
    }
    
    //删除链表中的指定结点(如果包含多个指定结点,只会删除第一个)
    public boolean deleteNode(Object obj){
        if(size == 0){
            System.out.println("链表为空!");
            return false;
        }
        //先在链表中查询是否包含该结点,找到之后获取该结点和其前一个结点
        Node previous = null;  //前一个结点
        Node current = head;  //当前结点
        while(current.data != obj){
            if(current.next == null){
                System.out.println("没有找到该结点!");
                return false;
            }
            previous = current;
            current = current.next;
        }
        if(current == head){
            this.deleteHeadNode();
        }else{
            previous.next = current.next;
            size--;
        }
        return true;
    }
    
    //正向打印链表
    public void display(){
        if(size == 0) System.out.println("链表为空!");
        Node n = head;
        while(n != null){
            System.out.print("<-"+n.data);
            n = n.next;
        }
        System.out.println();
    }
    
    //反向打印链表(用栈)
    public void printListFromTailToHead(Node node){
        if(node == null) System.out.println("链表为空!");
        Stack<Integer> sta = new Stack<Integer>();
        while(node != null){
            sta.push((Integer) node.data);  //先将链表压入栈中
            node = node.next;
        }
        while(!sta.empty()){
            System.out.print(sta.pop()+"<-");  //出栈
        }
        System.out.println();
    }
    
    //反向打印链表(递归)
    public void printListFromTailToHeadDiGui(Node node){
        if(node == null){
            System.out.println("链表为空!");
        }else{
            if(node.next != null){
                printListFromTailToHeadDiGui(node.next);
            }
            System.out.print(node.data+"<-");
        }
    }
    
    
    public static void main(String[] args) {
        LinkedListOnePoint list = new LinkedListOnePoint();
        System.out.println(list.isEmpty());            //true
        System.out.println(list.size());               //0
        list.display();                                //链表为空!
        list.printListFromTailToHead(list.head);       //链表为空!
        
        list.insertInHead(0);
        list.insertInHead(1);
        list.insertInHead(2);
        list.insertInHead(3);        
        list.display();                                //<-3<-2<-1<-0
        list.printListFromTailToHead(list.head);       //0<-1<-2<-3<-
        list.printListFromTailToHeadDiGui(list.head);  //0<-1<-2<-3<-
        System.out.println(list.isEmpty());            //false
        System.out.println(list.size());               //4
        System.out.println(list.containObject(1));     //true
    }
}

相关文章

  • 静态链表及C#实现

    静态链表 静态链表是用数组模拟动态链表。 静态链表结构描述 首先,静态链表使用数组来模拟动态链表。数组存放一个节点...

  • 动态链表与静态链表

    动态链表与静态链表 1. 静态链表 静态链表概述 从他的意义上讲,静态链表像是对没有指针的语言缺陷而产生这么一个补...

  • 数据结构——线性表

    线性表分为顺序存储结构和链式存储结构(单链表,静态链表,循环链表,双向链表)。 单链表(**一种动态结构,所占空间...

  • 13-C语言链表

    链表 链表就是将零碎的内存组织起来 静态链表 动态链表 空链表只有头指针和一个节点,并且节点没有数据, 也没有下一...

  • iOS知识复习笔记(19)---数据结构和算法1

    数组和链表的区别 数组静态分配内存,链表动态分配内存 数组内存中连续,链表不连续 数组元素在栈区,链表在堆区 数组...

  • C语言实现静态链表

    静态链表(单链表的一种形式) 有时,也可以借用一维数组来描述线性链表,我们称这种链表为静态链表。 静态链表需要实现...

  • 线性表的静态链表

    静态链表定义 静态链表的增删

  • 25_静态单链表的实现

    关键词: 单链表的一个缺点、静态单链表设计思路、静态单链表的继承层次结构、静态单链表的实现思路、静态单链表的实现 ...

  • 2018-03-19 静态链表

    用数组描述的链表叫做静态链表,这种描述方法叫做游标实现法。 (因为有些语言并没有指针,为了模拟动态链表,所以这种方...

  • 线性表

    1.线性表 1.1 顺序表(顺序存储) 静态分配 动态分配 1.2 单链表 单链表定义 不带头节点的单链表插入操作...

网友评论

      本文标题:动态链表与静态链表

      本文链接:https://www.haomeiwen.com/subject/paymuftx.html