zoukankan      html  css  js  c++  java
  • 单链表——基本操作

    1.获取链表第i个数据的算法思路

    1. 声明一个结点p指向链表第一个结点,初始化j从1开始
    2. 当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1
    3. 若到链表末尾p为空,则说明第i个元素不存在
    4. 否则查找成功,返回结点p的数据

    2.单链表第i个数据插入结点的算法思路

    1. 声明一结点p指向链表第一个结点,初始化j从1开始
    2. 当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1
    3. 若到链表末尾p为空,则说明第i个元素不存在
    4. 否则查找成功,在系统中生成一个空结点s
    5. 将数据元素e赋值给s->data
    6. 单链表的插入标准语句s->next=p->next;p->next=s
    7. 返回成功

    3.单链表第i个数据删除结点的算法思路

    1. 声明一结点p指向链表第一个结点,初始化j从1开始
    2. 当j<i时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1
    3. 若到链表末尾p为空,则说明第i个元素不存在
    4. 否则查找成功,将欲删除的结点p->next赋值给q
    5. 单链表的删除标准语句p->next=q->next
    6. 将q结点中的数据赋值给e,作为返回
    7. 释放q结点
    8. 返回成功

    分析一下刚才我们讲解的单链表插入和删除算法,我们发现,它们其实都是由两部分组成:第一部分就是遍历查找第i个结点;第二部分就是插入和删除结点。

    4.单链表整表创建的算法思路

    1. 声明一结点p和计数器变量i
    2. 初始化一空链表L
    3. 让L的头结点的指针指向NULL,即建立一个带头结点的单链表
    4. 循环:
    • 生成一新结点赋值给p
    • 随机生成一数字赋值给p的数据域p->data
    • 将p插入到头结点与前一新节点之间

         头插法,尾插法

    5.单链表的整表删除

    1. 声明一结点p和q
    2. 将第一个结点赋值给p
    3. 循环:
    • 将下一结点赋值给q
    • 释放p
    • 将q赋值给p

    Java代码实现,以下代码实现了单链表的各种操作  

    /**
     * 结点类的描述
     * 
     * 单链表是由若干个结点连接而成,要实现单链表,首先需要设计结点类
     * 
     * 结点类由data和next组成
     * 
     * data是数据域,用来存放数据元素的值
     * next是指针域,用来存放后继结点的地址
     * 
     * @author acer
     *
     */
    public class Node
    {
        private Object data; //存放结点值
        
        private Node next; //后继结点的引用
        
        //无参数时的构造方法
        public Node()
        {
            this(null, null);
        }
        
        //带一个参数的构造方法
        public Node(Object data)
        {
            this(data, null);
        }
        
        //带两个参数的构造方法
        public Node(Object data, Node next)
        {
            this.data = data;
            this.next = next;
        }
    
        public Object getData()
        {
            return data;
        }
    
        public void setData(Object data)
        {
            this.data = data;
        }
    
        public Node getNext()
        {
            return next;
        }
    
        public void setNext(Node next)
        {
            this.next = next;
        }
    }

    创建一个接口

    public interface IList
    {
        public void clear();
        public boolean isEmpty();
        public int length();
        public Object get(int i) throws Exception;
        public void insert(int i, Object x) throws Exception;
        public void remove(int i) throws Exception;
        public int indexOf(Object x);
        public void display();
    }
    /**
     * 单链表类的描述
     * 
     * 由于单链表只需一个头指针就能唯一的标示它,所以单链表类的成员变量只需设置一个头指针即可
     * 
     * @author acer
     * 
     */
    public class LinkList implements IList
    {
        //单链表的头指针
        private Node head;
    
        public LinkList()
        {
            //初始化头结点
            head = new Node();
        }
    
        public LinkList(int n, boolean Order) throws Exception
        {
            this();
            if (Order)
            {
                create1(n);
            } else
            {
                create2(n);
            }
        }
    
        // 用尾插法顺序建立单链表,其中n为单链表的结点个数
        public void create1(int n) throws Exception
        {
            //构造用于输入对象
            Scanner sc = new Scanner(System.in);
            
            for(int j = 0; j < n; j++)
            {
                //生成新结点,插入到表尾
                insert(length(), sc.next());
            }
        }
    
        // 用头插法逆位序建立单链表,其中n为单链表的结点个数
        public void create2(int n) throws Exception
        {
            /*
             * 构造用于输入对象
             * 
             * Scanner 使用分隔符模式将其输入分解为标记,默认情况下该分隔符模式与空白匹配
             * 然后可以使用不同的 next 方法将得到的标记转换为不同类型的值。
             */
            Scanner sc = new Scanner(System.in);
    
            for (int j = 0; j < n; j++)
            {
                //生成新结点,插入到表头
                insert(0, sc.next());
            }
        }
    
        // 将一个已经存在的带头结点单链表置为空表
        @Override
        public void clear()
        {
            head.setData(null);
            
            head.setNext(null);
        }
    
        // 判断带头结点的单链表是否为空
        @Override
        public boolean isEmpty()
        {
            return head.getNext() == null;
        }
    
        // 求带头结点的单链表的长度
        @Override
        public int length()
        {
            Node p = head.getNext();
            
            int lenth = 0;
            
            while(p != null)
            {
                p = p.getNext();
                
                ++lenth;
            }
            
            return lenth;
        }
    
        /*
         * 读取带头结点的单链表中的第i个结点
         * 
         * 时间复杂度为O(n)
         */
        @Override
        public Object get(int i) throws Exception
        {
            // 初始化,p指向首结点,j为计数器
            Node p = head.getNext();
    
            int j = 0;
    
            // 从首结点开始向后查找,直到p指向第i个结点或p为空
            while (p != null && j < i)
            {
                // 指向后继结点
                p = p.getNext();
    
                // 极速器加1
                ++j;
            }
    
            // i小于0或者大于表长减1
            if (j > i || p == null)
            {
                // 抛出异常
                throw new Exception("第" + i + "个元素不存在");
            }
    
            // 返回结点p的数据域的值
            return p.getData();
        }
    
        /*
         * 在带头结点的单链表中的第i个结点之前插入一个值为x的新结点
         * 
         * 时间复杂度为O(n)
         */
        @Override
        public void insert(int i, Object x) throws Exception
        {
            // 初始化,p指向首结点,j为计数器
            Node p = head;
    
            int j = -1;
    
            // 寻找第i个结点的前驱
            while (p != null && j < i - 1)
            {
                p = p.getNext();
    
                // 计数器加1
                ++j;
            }
    
            // i不合法
            if (j > i - 1 || p == null)
            {
                // 抛出异常
                throw new Exception("插入位置不合法");
            }
    
            // 生成新结点
            Node s = new Node(x);
    
            // 修改链,使新结点插入到单链表中
            s.setNext(p.getNext());
    
            p.setNext(s);
        }
    
        /*
         * 在不带头结点的单链表的第i个结点之前插入一个数据域值为x的新结点
         * 
         * 时间复杂度为O(n)
         */
        public void insert2(int i, Object x) throws Exception
        {
            // 初始化,p指向首结点,j为计数器
            Node p = head;
    
            int j = 0;
    
            // 用i = -11测试
            while (p != null && j < i - 1)
            {
                p = p.getNext();
    
                ++j;
            }
    
            if (j > i || p == null)
            {
                throw new Exception("插入位置不合法");
            }
    
            Node s = new Node(x);
    
            // 插入位置为表头时
            if (i == 0)
            {
                s.setNext(head);
    
                head = s;
            }
            // 插入位置为表的中间或表尾时
            else
            {
                s.setNext(p.getNext());
    
                p.setNext(s);
            }
        }
    
        /*
         * 删除单链表中的第i个结点
         * 
         * 时间复杂度为O(n)
         */
        @Override
        public void remove(int i) throws Exception
        {
            // 初始化,p指向首结点,j为计数器
            Node p = head;
    
            int j = -1;
    
            // 寻找第i个结点的前驱
            while (p.getNext() != null && j < i - 1)
            {
                p = p.getNext();
    
                ++j;
            }
            if (j > i - 1 || p.getNext() == null)
            {
                throw new Exception("删除位置不合法");
            }
    
            // 修改链指针,使待删除结点从单链表中脱离
            p.setNext(p.getNext().getNext());
    
        }
    
        /*
         * 在单链表中查找值为x的结点
         * 
         * 时间复杂度为O(n)
         */
        @Override
        public int indexOf(Object x)
        {
            // 初始化,p指向首结点,j为计数器
            Node p = head.getNext();
    
            int j = 0;
    
            // 下面从单链表中的首结点开始查找,直到p.getData()为x或到达单链表的表尾
            while (p != null && !p.getData().equals(x))
            {
                // 指向下一个结点
                p = p.getNext();
    
                // 计数器加1
                ++j;
            }
    
            // 若p指向单链表中的某个结点,返回值为x的结点在单链表中的位置
            if (p != null)
            {
                return j;
            } else
            {
                // 值为x的结点不在链表中
                return -1;
            }
        }
    
        // 输出单链表中的所有结点
        @Override
        public void display()
        {
            //取出带头结点的单链表中的首结点
            Node p = head.getNext();
            
            while(p != null)
            {
                //输出结点的值
                System.out.print(p.getData() + " ");
                
                //取下一个结点
                p = p.getNext();
            }
            
            //换行
            System.out.println();
        }
    }
  • 相关阅读:
    团队项目总结
    第二阶段团队绩效评分
    “转赚”------使用说明
    团队站立会议14
    团队站立会议13
    团队站立会议12
    团队站立会议11
    团队站立会议10
    LocalDate 今天是一年中的第几天?
    MAC系统Java环境搭建
  • 原文地址:https://www.cnblogs.com/thiaoqueen/p/8813305.html
Copyright © 2011-2022 走看看