精华内容
下载资源
问答
  • 单链表双链表

    2013-12-02 18:55:54
    链表的一些操作都有,注释也详细,做了一些代码优化,比传统的链表创建以及插入多了一些合理性,那就是一般写链表的,都不会先创建插入,再排序,那样浪费时间,影响效率,当然第二个代码才是,第一个代码是传统的...
  • 数据结构中 单链表 双链表 循环链表 c语言代码。
  • 单链表 双向链表 基于Java的单链表双向链表实现

    一、单链表

    单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

    image

    在开头插入。在链接列表中插入新节点的最简单位置是开始。
    image

    从头开始删除。删除链表中的第一个节点也很容易

    image
    在末尾插入。要在链接列表的末尾插入一个节点,我们维护一个指向列表中最后一个节点的链接。
    image

    /**
     * 单链表
     */
    class SingleLinked {
        Node HeadNode = new Node(0, "", "");//创建链表时头结点便已经创建完成在
    
        //增加节点
        public void add(Node node) {
            Node temp = HeadNode;
            while (temp.next != null) temp = temp.next;
            temp.next = node;
        }
    
        /**
         * 按no的顺序添加节点
         */
        public void addNodeByOrder(Node node) {
            Node temp = HeadNode;
            while (temp.next != null) {//如果没有大小匹配的,就放在末尾
                if (temp.no < node.no && temp.next.no > node.no) break;
            }
            if (temp.next == null) {
                temp.next = node;
            } else {
                node.next = temp.next;
                temp.next = node;
            }
        }
    
        /**
         * 根据no修改信息
         */
        public void updateNodeByNo(Node newNode) {
            Node temp = HeadNode;
            while (true) {
                if (temp.no == newNode.no) {
                    temp.name = newNode.name;
                    temp.nickName = newNode.nickName;
                    break;
                }
                //最后一个节点
                if (temp.next == null) throw new RuntimeException("no错误");
                temp = temp.next;
            }
        }
    
        /**
         * 删除节点
         */
        public void deletNodeByNo(int no) {
            Node temp = HeadNode;
            if (temp.next == null) {
                System.out.println("链表为空");
                return;
            }
            Node pre = temp;//前驱指针
            temp = temp.next;
            while (true) {
                if (temp.no == no) {
                    pre.next = temp.next;
                    break;
                }
                if (temp.next == null) break;
                pre = temp;
                temp = temp.next;
            }
        }
    
        /**
         * 遍历当前链表
         */
        public void showLinked() {
            if (HeadNode.next == null) {
                System.out.println("链表为空");
                return;
            }
            Node temp = HeadNode.next;
            while (true) {
                System.out.println(temp);
                if (temp.next == null) break;
                temp = temp.next;
            }
        }
    }
    

    节点类

    /**
     * 节点类
     */
    class Node {
        public int no;//编号
        public String name;
        public String nickName;
        public Node next;//指向下一个节点
    
        //节点的构造方法
        public Node(int no, String name, String nickName) {
            this.no = no;
            this.name = name;
            this.nickName = nickName;
            this.next = null;
        }
    
        @Override
        public String toString() {
            return new StringJoiner(", ", Node.class.getSimpleName() + "[", "]")
                    .add("no=" + no)
                    .add("name='" + name + "'")
                    .add("nickName='" + nickName + "'")
                    .toString();
        }
    }
    

    二、双向链表

    双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表

    image.jpeg

    /**
     * 链表类
     */
    class DoublyLinked {
    
        private DoubleNode FirstNode = new DoubleNode(0, "");//创建链表时先初始化一个头结点
    
        /**
         * 最后一个节点后
         *
         * @param node
         */
        public void add(DoubleNode node) {
            DoubleNode temp = FirstNode;
            while (temp.getNext() != null) {
                temp = temp.getNext();
            }
            temp.setNext(node);
            node.setPre(temp);
        }
    
        /**
         * 按顺序添加节点
         */
        public void addByOrder(DoubleNode node) {
            DoubleNode temp = FirstNode;
            while (true) {
                if (temp.getNo() == node.getNo()) {
                    System.out.println("节点已经存在");
                    return;
                }
                if (temp.getNo() > node.getNo()) {//中间插入
                    temp.getPre().setNext(node);
                    node.setPre(temp.getPre());
                    node.setNext(temp);
                    temp.setPre(node);
                    break;
                }
                if (temp.getNext() == null) {//最后一个节点
                    temp.setNext(node);
                    node.setPre(temp);
                    break;
                }
                temp = temp.getNext();
            }
        }
    
        /**
         * 遍历链表
         */
        public void showLinked() {
            if (FirstNode.getNext() == null) {
                System.out.println("链表为空");
                return;
            }
            DoubleNode temp = FirstNode.getNext();
            while (true) {
                System.out.println(temp);
                if (temp.getNext() == null) break;
                temp = temp.getNext();
            }
        }
    
        /**
         * 删除节点
         */
        public void deleteNode(int no) {
            if (FirstNode.getNext() == null) {
                System.out.println("链表为空");
                return;
            }
            DoubleNode temp = FirstNode.getNext();
            while (true) {
                if (temp.getNo() == no) {
                    temp.getPre().setNext(temp.getNext());
                    temp.getNext().setPre(temp.getPre());
                }
                if (temp.getNext() == null) break;
                temp = temp.getNext();
            }
        }
    
        /**
         * 修改节点信息
         */
        public void updateNode(DoubleNode newNode) {
            if (FirstNode.getNext() == null) {
                System.out.println("链表为空");
                return;
            }
            DoubleNode temp = FirstNode.getNext();
            while (true) {
                if (temp.getNo() == newNode.getNo()) {
                    temp.setName(newNode.getName());
                    break;
                }
                if (temp.getNext() == null) {
                    System.out.println("没有相关节点");
                    break;
                }
                temp = temp.getNext();
            }
        }
    }
    

    节点类

    /**
     * 节点类
     */
    class DoubleNode {
        private int no;
        private String name;
        private DoubleNode next;//指向后一个节点
        private DoubleNode pre;//指向前一个节点
    
        public DoubleNode(int no, String name) {
            this.no = no;
            this.name = name;
        }
    
        public int getNo() {
            return no;
        }
    
        public void setNo(int no) {
            this.no = no;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public DoubleNode getNext() {
            return next;
        }
    
        public void setNext(DoubleNode next) {
            this.next = next;
        }
    
        public DoubleNode getPre() {
            return pre;
        }
    
        public void setPre(DoubleNode pre) {
            this.pre = pre;
        }
    
        @Override
        public String toString() {
            return new StringJoiner(", ", DoubleNode.class.getSimpleName() + "[", "]")
                    .add("no=" + no)
                    .add("name='" + name + "'")
                    .toString();
        }
    }
    
    展开全文
  • josephu问题 单链表 双链表 分别实现
  • 关于c语言的程序与习题 有关于顺序链表 单链表 双链表 栈等程序,运用相关软件打开并运行,就可以看到效果
  • 数据结构课程资源 包括单链表 双链表 堆栈 二叉树 等程序编写。有利于学习数据结构知识 该资源为程序文件,可直接运行,调试无误。
  • 链表特点(单链表 双链表) 优点:插入和删除非常快。因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作。 缺点:当需要查找某一个节点的时候就需要一个节点一个节点...

    链表特点(单链表 双链表)

    优点:插入和删除非常快。因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作。

    缺点:当需要查找某一个节点的时候就需要一个节点一个节点去访问,这样所花的时候就比较多了。(顺序表可以弥补这缺点,但插入和删除就非常耗性能)

     

    单链表

    单链表的构成:必须要有一个链表头(head),每个节点里面有一个Next用于指向下一个节点(类似于指针)。最后一个节点的Next为null来标识链表的尾。

     

    如下图

     

     

    代码实现

     1 /* ------------  单链表 ------------- */
     2 //链表头
     3 SingleLink head = new SingleLink();
     4 SingleLink node;
     5  
     6 //添加节点
     7 node = new SingleLink(1, "刘德华");
     8 SingleLink.Add(ref head, node);
     9  
    10 node = new SingleLink(2, "张学友");
    11 SingleLink.Add(ref head, node);
    12  
    13 node = new SingleLink(3, "郭富城");
    14 SingleLink.Add(ref head, node);
    15  
    16 node = new SingleLink(4, "黎明");
    17 SingleLink.Add(ref head, node);
    18  
    19  
    20 //删除节点
    21 SingleLink.Remove(ref head, 2);
    22  
    23 //遍历所有节点
    24 SingleLink cursor = head;
    25 while (cursor.Next != null)
    26 {
    27     Console.WriteLine(cursor.Next.ToString());
    28     cursor = cursor.Next;
    29 }
    30  
    31  
    32 /// <summary>
    33 /// 单链表
    34 /// </summary>
    35 public class SingleLink
    36 {
    37     public int No { get; set; }
    38  
    39     public string Name { get; set; }
    40  
    41     //指向下一个节点(有点像指针)
    42     public SingleLink Next { get; set; }
    43  
    44     public SingleLink() { }
    45  
    46     public SingleLink(int no, string name)
    47     {
    48         this.No = no;
    49         this.Name = name;
    50     }
    51  
    52  
    53     /// <summary>
    54     /// 添加
    55     /// </summary>
    56     /// <param name="head">链表头</param>
    57     /// <param name="addNode">添加节点</param>
    58     public static void Add(ref SingleLink head, SingleLink addNode)
    59     {
    60         SingleLink cursor = head;
    61         while (cursor.Next != null)
    62         {
    63             cursor = cursor.Next;
    64         }
    65         cursor.Next = addNode;
    66     }
    67  
    68  
    69     /// <summary>
    70     /// 删除
    71     /// </summary>
    72     /// <param name="head">链表头</param>
    73     /// <param name="no">删除编号</param>
    74     public static void Remove(ref SingleLink head, int no)
    75     {
    76         SingleLink cursor = head;
    77         while (cursor.Next !=null)
    78         {
    79             if (cursor.Next.No == no)
    80             {
    81                 cursor.Next = cursor.Next.Next;
    82                 return;
    83             }
    84             cursor = cursor.Next;
    85         }
    86     }
    87  
    88  
    89     /// <summary>
    90     /// 输入信息(重写ToString方法)
    91     /// </summary>
    92     /// <returns></returns>
    93     public override string ToString()
    94     {
    95         return "No---> " + No + "  Name---> " + Name;
    96     }
    97 }
    View Code

     

     

     

     代码分析图

     

     

     

     

     

    双链表

       双链表的构成:双链表跟单链表差不多,也是必须要有一个链表头(head),每个节点里面有一个Next,最后一个节点的Next为null来标识链表的尾。只不过双链表在每个节点上面添加一个Prev,来标识当前节点的上一个节点。

     

    如图:

     

    代码实现

      1 /* ------------  双链表 ------------- */
      2 //链表头
      3 DoubleLink head = new DoubleLink();
      4 DoubleLink node;
      5  
      6 //添加节点
      7 node = new DoubleLink(1,"刘德华");
      8 DoubleLink.Add(ref head, node);
      9  
     10 node = new DoubleLink(2, "张学友");
     11 DoubleLink.Add(ref head, node);
     12  
     13 node = new DoubleLink(3, "郭富城");
     14 DoubleLink.Add(ref head, node);
     15  
     16 node = new DoubleLink(4, "黎明");
     17 DoubleLink.Add(ref head, node);
     18  
     19 //删除节点
     20 DoubleLink.Remove(ref head,3);
     21  
     22 //遍历所有节点
     23 DoubleLink cursor = head;
     24 while (cursor.Next != null)
     25 {
     26     Console.WriteLine(cursor.Next.ToString());
     27     cursor = cursor.Next;
     28 }
     29  
     30  
     31 /// <summary>
     32 /// 双链表
     33 /// </summary>
     34 public class DoubleLink
     35 {
     36     public int No { get; set; }
     37  
     38     public string Name { get; set; }
     39  
     40     //下个节点
     41     public DoubleLink Prev { get; set; }
     42  
     43     //上个节点
     44     public DoubleLink Next { get; set; }
     45  
     46     public DoubleLink() { }
     47  
     48     public DoubleLink(int no, string name)
     49     {
     50         this.No = no;
     51         this.Name = name;
     52     }
     53  
     54  
     55     /// <summary>
     56     /// 添加
     57     /// </summary>
     58     /// <param name="head">链表头</param>
     59     /// <param name="addNode"></param>
     60     public static void Add(ref DoubleLink head, DoubleLink addNode)
     61     {
     62         DoubleLink cursor = head;
     63         while (cursor.Next != null)
     64         {
     65             cursor = cursor.Next;
     66         }
     67         cursor.Next = addNode;
     68         cursor.Next.Prev = cursor;
     69     }
     70  
     71  
     72     /// <summary>
     73     /// 删除
     74     /// </summary>
     75     /// <param name="head">链表头</param>
     76     /// <param name="no">删除编号</param>
     77     public static void Remove(ref DoubleLink head, int no)
     78     {
     79         DoubleLink cursor = head.Next;
     80         while (cursor != null)
     81         {
     82             if (cursor.No == no)
     83             {
     84                 //防止是删除最后一个
     85                 if (cursor.Next != null)
     86                 {
     87                     cursor.Next.Prev = cursor.Prev;
     88                 }
     89                 cursor.Prev.Next = cursor.Next;
     90                 return;
     91             }
     92             cursor = cursor.Next;
     93         }
     94     }
     95  
     96  
     97     /// <summary>
     98     /// 输入信息(重写ToString方法)
     99     /// </summary>
    100     /// <returns></returns>
    101     public override string ToString()
    102     {
    103         return "No---> " + No + "  Name---> " + Name;
    104     }
    105 }
    View Code

     

     

    代码分析图

     

     

     

     

     

     

    环形链表

      环形链表是在单链表基础之上把尾指向头就构成了一个环形的链表了。也就是单链表最后一个节点的Next指Head就可以了。

     

         如图:

      

     

     

    代码实现

      1 //环形链表
      2 LoopLink head = new LoopLink();
      3 LoopLink node;
      4 
      5 
      6 //添加节点
      7 node = new LoopLink(1, "刘德华");
      8 LoopLink.Add(ref head, node);
      9 
     10 node = new LoopLink(2, "张学友");
     11 LoopLink.Add(ref head, node);
     12 
     13 node = new LoopLink(3, "郭富城");
     14 LoopLink.Add(ref head, node);
     15 
     16 node = new LoopLink(4, "黎明");
     17 LoopLink.Add(ref head, node);
     18 
     19 LoopLink.Remove(ref head, 2);
     20 
     21 //遍历所有节点(遍历需要拿到它的头或者尾来标识链表的结束位置,我是拿到头来遍历的)
     22 LoopLink cursor = head;
     23 LoopLink first = head;
     24 //首先输出头的信息
     25 Console.WriteLine(head);
     26 //遍历所有节点,如果遍历到头节点就退出循环,链表打印完成
     27 while (!Object.ReferenceEquals(cursor.Next, first))
     28 {
     29     Console.WriteLine(cursor.Next.ToString());
     30     cursor = cursor.Next;
     31 }
     32 
     33 
     34 
     35 /// <summary>
     36 /// 环形链表
     37 /// </summary>
     38 class LoopLink
     39 {
     40 
     41     public int No { get; set; }
     42 
     43     public string Name { get; set; }
     44 
     45     public LoopLink Next { get; set; }
     46 
     47     public LoopLink() { }
     48 
     49     public LoopLink(int no, string name)
     50     {
     51         this.No = no;
     52         this.Name = name;
     53     }
     54 
     55     public static LoopLink Cursor { get; set; }
     56 
     57     /// <summary>
     58     /// 添加
     59     /// </summary>
     60     /// <param name="head">链表头</param>
     61     /// <param name="addNode">所要添加节点</param>
     62     public static void Add(ref LoopLink head, LoopLink addNode)
     63     {
     64         if (head.Next == null)
     65         {
     66             head = addNode;
     67             head.Next = addNode;
     68             Cursor = head;
     69         }
     70         else
     71         {
     72             Cursor.Next = addNode;
     73             addNode.Next = head;
     74             Cursor = Cursor.Next;
     75         }
     76     }
     77 
     78 
     79     /// <summary>
     80     /// 删除节点
     81     /// </summary>
     82     /// <param name="head">链表头</param>
     83     /// <param name="no">所要删除编号</param>
     84     public static void Remove(ref LoopLink head, int no)
     85     {
     86         LoopLink cur = head;
     87 
     88         while (true)
     89         {
     90             if (cur.Next.No == no)
     91             {
     92                 cur.Next = cur.Next.Next;
     93                 return;
     94             }
     95             cur = cur.Next;
     96         }
     97     }
     98 
     99 
    100     /// <summary>
    101     /// 输入信息(重写ToString方法)
    102     /// </summary>
    103     /// <returns></returns>
    104     public override string ToString()
    105     {
    106         return "No---> " + No + "  Name---> " + Name;
    107     }
    108 }
    View Code

     

     

     

    扩展训练(面试题)

           

      题目:有一颗炸弹,有N个人围成一个圆形,从第K个人开始数数,数M就退出圆。最后算出留下来要被炸死是第几个人。请用代码实现。

     

     

      代码如下:

     

      1 //N个人
      2 int n = 5;
      3 
      4 //第K个人开始数数
      5 int k = 3;
      6 
      7 //数到M就退出
      8 int m = 4;
      9 
     10 Game head = new Game();
     11 
     12 //构建一个由N个人组成的圆形
     13 Game.Add(ref head, n);
     14 //查找谁会被炸死
     15 Game.Bomb(ref head, k, m);
     16 
     17 
     18 
     19 /// <summary>
     20 /// 游戏类
     21 /// </summary>
     22 public class Game
     23 {
     24     public int No { get; set; }
     25 
     26     public Game Next { get; set; }
     27 
     28     public Game() { }
     29 
     30     public Game(int no)
     31     {
     32         this.No = no;
     33     }
     34 
     35 
     36     public static void Add(ref Game head, int n)
     37     {
     38         Game cursor = null;
     39         for (int i = 0; i < n; i++)
     40         {
     41             Game temp = new Game(i+1);
     42             if (i == 0)
     43             {
     44                 head.Next = temp;
     45                 head = temp;
     46                 cursor = head;
     47             }
     48             else
     49             {
     50                 cursor.Next = temp;
     51                 temp.Next = head;
     52                 cursor = cursor.Next;
     53             }
     54         }
     55     }
     56 
     57 
     58     /// <summary>
     59     /// 查找谁会被炸死
     60     /// </summary>
     61     /// <param name="head">链表头</param>
     62     /// <param name="k">开始数数的人</param>
     63     /// <param name="m">数几就退出圆圈</param>
     64     public static void Bomb(ref Game head,int k, int m)
     65     {
     66         Game tail = head;
     67 
     68         //拿到最后一个节点
     69         while (!Object.ReferenceEquals(tail.Next,head))
     70         {
     71             tail = tail.Next;
     72         }
     73 
     74 
     75         //从第K个人开始数数
     76         for (int i = 0; i < k; i++)
     77         {
     78             head = head.Next;
     79             tail = tail.Next;
     80         }
     81 
     82 
     83         //当头跟尾是同一个节点说明找到最终的节点
     84         int mark = 1;
     85         while (!object.ReferenceEquals(tail,head))
     86         {
     87             for (int i = 0; i < m-1; i++)
     88             {
     89                 head = head.Next;
     90                 tail = tail.Next;
     91             }
     92 
     93             Console.WriteLine(@""+mark+@"个安全退出人的编号:"+head.No);
     94 
     95             head = head.Next;
     96             tail.Next = head;
     97             mark++;
     98         }
     99 
    100         Console.WriteLine(@"最后被炸死人的编号:" + head.No);
    101     }
    102 }
    View Code

     

     

     

     

      总结:

        1.扩展训练题其实考的就是环形链表,这个题目跟约瑟夫问题是一样的(实现思路是一样的)

        2.“程序=算法+数据结构”,但是在我们真正开发的时候算法和数据结构用到很少,一般比较大型项目或者复杂度比较高项目和游戏里面可能才会用到这些,但是我们还是要了解,说不定面试考到了呢?(答对了会加分的哦!^_^)

        3.链表什么时候会用到呢?比如说象棋里面有悔棋,我们就可以用双向链表来实现,这样就可以悔到上一步也可以下一步了,还有很多应用场景。而单链表的话像LinkedList就是用单链表实现的(但是LinkedList被List代替,不推荐用LinkedList,推荐用List.自己查一下为什么?)

     

      

     

      (本人学识有限,文章如有误,愿见谅。希望能指出来,以免误人子弟了。^_^)

     

    转载于:https://www.cnblogs.com/qq610540622/p/4625555.html

    展开全文
  • 单链表双向链表应用

    2020-07-14 18:07:16
    目录 1 单链表的应用实例 ...1.4.5 合并两个有序的单链表,合并之后的链表依然有序 2 双向链表 2.1 添加 2.2 删除 1) 链表是以节点的方式来存储, 是链式存储 2) 每个节点包含 data 域, next 域:指

    目录

    1 单链表的应用实例

    1.1 添加

    1.1.1 直接添加到尾部

    1.1.2 插入到指定位置

    1.2 修改节点

    1.3 删除节点

    1.4 应用

    1.4.1 求单链表有效节点个数

    1.4.2 查找单链表中的倒数第k个节点

    1.4.3 单链表的反转

    1.4.4 从头到尾打印单链表

    1.4.5 合并两个有序的单链表,合并之后的链表依然有序

    2 双向链表

    2.1 添加

    2.2 删除


    1) 链表是以节点的方式来存储, 是链式存储
    2) 每个节点包含 data 域, next 域:指向下一个节点.
    3) 发现 链表的各个节点不一定是连续存储.
    4) 链表分 带头节点的链表和 没有头节点的链表,根据实际的需求来确定

    1 单链表的应用实例

    1.1 添加

    1.1.1 直接添加到尾部

    • 先创建一个head头结点,作用就是表示单链表的头
    • 每添加一个节点,就直接加入到链表的最后

    思路,当不考虑编号顺序时
    1. 找到当前链表的最后节点
    2. 将最后这个节点的next 指向 新的节点

    		//因为head节点不能动,因此我们需要一个辅助遍历 temp
    		HeroNode temp = head;
    		//遍历链表,找到最后
    		while(true) {
    			//找到链表的最后
    			if(temp.next == null) {//
    				break;
    			}
    			//如果没有找到最后, 将将temp后移
    			temp = temp.next;
    		}
    		//当退出while循环时,temp就指向了链表的最后
    		//将最后这个节点的next 指向 新的节点
    		temp.next = heroNode;

    1.1.2 插入到指定位置

    1. 找到要插入的位置,通过辅助变量遍历
    2. 新的节点.next=temp(辅助变量).next
    3. 将temp.next=新的节点
    		//因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置
    		//因为单链表,因为我们找的temp 是位于 添加位置的前一个节点,否则插入不了
    		HeroNode temp = head;
    		boolean flag = false; // flag标志添加的编号是否存在,默认为false
    		while(true) {
    			if(temp.next == null) {//说明temp已经在链表的最后
    				break; //
    			} 
    			if(temp.next.no > heroNode.no) { //位置找到,就在temp的后面插入
    				break;
    			} else if (temp.next.no == heroNode.no) {//说明希望添加的heroNode的编号已然存在
    				
    				flag = true; //说明编号存在
    				break;
    			}
    			temp = temp.next; //后移,遍历当前链表
    		}
    		//判断flag 的值
    		if(flag) { //不能添加,说明编号存在
    			System.out.printf("准备插入的英雄的编号 %d 已经存在了, 不能加入\n", heroNode.no);
    		} else {
    			//插入到链表中, temp的后面
    			heroNode.next = temp.next;
    			temp.next = heroNode;
    		}

    1.2 修改节点

    通过遍历找到该节点,修改节点信息

    1.3 删除节点

    1. 先找到需要删除的节点的前一个节点temp
    2. temp.next=temp.next.next
    3. 被删除的节点将不会有其他引用指向,会被垃圾回收机制回收

    1.4 应用

    1.4.1 求单链表有效节点个数

    	//方法:获取到单链表的节点的个数(如果是带头结点的链表,需求不统计头节点)
    	/**
    	 * 
    	 * @param head 链表的头节点
    	 * @return 返回的就是有效节点的个数
    	 */
    	public static int getLength(HeroNode head) {
    		if(head.next == null) { //空链表
    			return 0;
    		}
    		int length = 0;
    		//定义一个辅助的变量, 这里我们没有统计头节点
    		HeroNode cur = head.next;
    		while(cur != null) {
    			length++;
    			cur = cur.next; //遍历
    		}
    		return length;
    	}

    1.4.2 查找单链表中的倒数第k个节点

    思路

    1.  编写一个方法,接收 head 节点,同时接收一个 index
    2.  index 表示是倒数第 index 个节点
    3. 先把链表从头到尾遍历,得到链表的总的长度 getLength
    4.  得到 size 后,我们从链表的第一个开始遍历 (size-index)个,就可以得到
    5.  如果找到了,则返回该节点,否则返回 nulll
    	public static HeroNode findLastIndexNode(HeroNode head, int index) {
    		//判断如果链表为空,返回null
    		if(head.next == null) {
    			return null;//没有找到
    		}
    		//第一个遍历得到链表的长度(节点个数)
    		int size = getLength(head);
    		//第二次遍历  size-index 位置,就是我们倒数的第K个节点
    		//先做一个index的校验
    		if(index <=0 || index > size) {
    			return null; 
    		}
    		//定义给辅助变量, for 循环定位到倒数的index
    		HeroNode cur = head.next; //3 // 3 - 1 = 2
    		for(int i =0; i< size - index; i++) {
    			cur = cur.next;
    		}
    		return cur;
    		
    	}

    1.4.3 单链表的反转

    定义一个新的链表

    从头到尾遍历链表,没遍历一个节点就把该节点取出来,并采用头插法插入新链表

    把原来的链表的head.next=新头结点.next

    	public static void reversetList(HeroNode head) {
    		//如果当前链表为空,或者只有一个节点,无需反转,直接返回
    		if(head.next == null || head.next.next == null) {
    			return ;
    		}
    		
    		//定义一个辅助的指针(变量),帮助我们遍历原来的链表
    		HeroNode cur = head.next;
    		HeroNode next = null;// 指向当前节点[cur]的下一个节点
    		HeroNode reverseHead = new HeroNode(0, "", "");
    		//遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表reverseHead 的最前端
    		//动脑筋
    		while(cur != null) { 
    			next = cur.next;//先暂时保存当前节点的下一个节点,因为后面需要使用
    			cur.next = reverseHead.next;//将cur的下一个节点指向新的链表的最前端
    			reverseHead.next = cur; //将cur 连接到新的链表上
    			cur = next;//让cur后移
    		}
    		//将head.next 指向 reverseHead.next , 实现单链表的反转
    		head.next = reverseHead.next;
    	}

    1.4.4 从头到尾打印单链表

    方法一:倒置链表然后打印

    •  缺陷:改变了链表的结构

    方法二:遍历链表,把每一个节点存入栈中,然后出栈

    	public static void reversePrint(HeroNode head) {
    		if(head.next == null) {
    			return;//空链表,不能打印
    		}
    		//创建要给一个栈,将各个节点压入栈
    		Stack<HeroNode> stack = new Stack<HeroNode>();
    		HeroNode cur = head.next;
    		//将链表的所有节点压入栈
    		while(cur != null) {
    			stack.push(cur);
    			cur = cur.next; //cur后移,这样就可以压入下一个节点
    		}
    		//将栈中的节点进行打印,pop 出栈
    		while (stack.size() > 0) {
    			System.out.println(stack.pop()); //stack的特点是先进后出
    		}
    	}

    1.4.5 合并两个有序的单链表,合并之后的链表依然有序

    同1.4.3单链表的倒置,新建一个链表,遍历两个链表,比较大小,在让原来的头结点指向新链表

    2 双向链表

    2.1 添加

    1. 先找到双向链表的最后这个节点
    2. temp.next = newHeroNode
    3. newHeroNode.pre = temp;

    2.2 删除

    1. 因为是双向链表,因此,我们可以实现自我删除某个节点
    2. 直接找到要删除的这个节点,比如 temp
    3. temp.pre.next = temp.next
    4. temp.next.pre = temp.pre;

     

     

     

     

     

     

     

    展开全文
  • NULL 博文链接:https://zhanhao.iteye.com/blog/1137409
  • Singly Linked List: 1. DestroyList 2. InsertList 3. DeleteList 4. TraverseList 5. SearchList 6. ReverseList 7. IsLoopList 8. ReverseEvenList 9. FindMidNode ...5. TraverseList_DuL
  • 头指针单链表 public class LinkedList { Node head; public static void main(String[] args) { LinkedList linkedList = new LinkedList(); linkedList.addAtRear(2); linkedList.addAtFront(1); ...

    头指针单链表

    public class LinkedList {
    	Node head;
    	public static void main(String[] args) {
    		LinkedList linkedList = new LinkedList();
    		linkedList.addAtRear(2);
    		linkedList.addAtFront(1);
    		linkedList.showAll();
    		linkedList.del(2);
    		linkedList.showAll();
    }
    	
    	public void showAll() {
    		if (isEmpty()) {
    			System.out.println("链表为空");
    		}
    		Node current = head;
    		while (current != null) {
    			System.out.print(current.data + " ");
    			current = current.next;
    		}
    	}
    	
    	public int del(int data) {
    		if (isEmpty()) {
    			throw new RuntimeException("链表为空");
    		}
    		if(head.data == data)
    		{
    			head = head.next;
    			return 1;
    		}
    		Node current = head;
    		while(current.next != null ) {
    			if(current.next.data == data) {
    				current.next = current.next.next;
    				return 1;
    			}
    			current = current.next;
    		}
    		return -1;
    	}
    	public void addAtFront(int data) {
    		Node node = new Node(data);
    		if (isEmpty()) {
    			head = node;
    			return ;
    		}
    		node.next = head;
    		head = node;
    	}
    	
    	public void addAtRear(int data) {
    		Node node = new Node(data);
    		if(isEmpty()) {
    			head = node;
    			return ;
    		}
    		Node current = head;
    		while (current.next != null) {
    			current = current.next;
    		}
    		current.next = node;
    	}
    	
    	public boolean isEmpty() {
    		return head == null;
    	}
    	
    }
    
    class Node{
    	int data;
    	Node next;
    	
    	public Node(int data) {
    		this.data = data;
    	}
    }
    

    头指针双向循环链表

    public class DoubleLinkedList {
    	public static void main(String[] args) {
    		DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
    		doubleLinkedList.addAtFront(1);
    		doubleLinkedList.addAtFront(2);
    		doubleLinkedList.showAll();
    	}
    
    	DoubleNode head;
    	
    	public void showAll() {
    		if (isEmpty()) {
    			System.out.println("链表为空");
    		}
    		System.out.println(head.data);
    		DoubleNode current = head.next;
    		while (current != head) {
    			System.out.println(current.data);
    			current = current.next;
    		}
    	}
    	
    	public int del(int data) {
    		if (isEmpty())
    			throw new RuntimeException("链表为空");
    		
    		if (head.data == data) {
    			DoubleNode next = head.next;
    			head.pre.next = head.next;
    			head.next.pre = head.pre;
    			head = next;
    			return 1;
    		}
    		DoubleNode current = head;
    		while (current.next != head) {
    			if (current.data == data) {
    				current.pre.next = current.next;
    				current.next.pre = head.pre;
    				return 1;
    			}
    			current = current.next;
    		}
    		return -1;
    	}
    
    	public void addAtFront(int data) {
    		DoubleNode node = new DoubleNode(data);
    		if (isEmpty()) {
    			head = node;
    			return;
    		}
    
    		DoubleNode current = head;
    		while (current.next != head) {
    			current = current.next;
    		}
    
    		node.next = head;
    		head.pre = node;
    
    		current.next = node;
    		node.pre = current;
    
    		head = node;
    	}
    
    	public boolean isEmpty() {
    		return head == null;
    	}
    
    	public DoubleNode getHead() {
    		return head;
    	}
    }
    
    class DoubleNode {
    	int data;
    	DoubleNode pre;
    	DoubleNode next;
    
    	public DoubleNode(int data) {
    		this.data = data;
    		this.pre = this;
    		this.next = this;
    	}
    }
    
    展开全文
  • 没有做到模块的可分离,感觉变量杂糅在一起了……但是实现效果还是很不错的,可能需要对所有代码非常熟悉才能进行修改。
  • //创建有n个元素的双向链表 并输入元素 void printlist(double_list *head);//遍历并且输出这些元素 int lengthlist(double_list *head);//得到现在双向链表中的元素的个数 void insertlist_f(double_list *head, ...
  • 文章目录一、线性表的顺序存储顺序存储结构的定义1、线性表的查找2、线性表的插入3、线性表的删除4、顺序表的合并二、线性表的链式存储单链表存储结构声明1、链表的初始化2、头插法建表3、尾插法建表4、按序号查找...
  • 新手,最近在学c#,请问有谁知道关于链表的视频,包括单链表,单循环链表循环链表等等,从链表最基础的开始讲的视频,里面介绍使用链表最基础的代码,谢了谢了!

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,260
精华内容 2,904
关键字:

单链表双链表