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

动态链表与静态链表

作者: 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
        }
    }
    

    相关文章

      网友评论

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

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