zoukankan      html  css  js  c++  java
  • 数据结构Java实现----链表

    一.单向链表(递归)

    MyLinkList类

      1 package List;
      2 
      3 // 单向链表
      4 public class MyLinkList {
      5     private Node root; // 根结点
      6     private int size; // 结点个数
      7     private int index; // 脚标
      8     private Object[] reData; // 保存数据的数组
      9 
     10     // 构造方法
     11     public MyLinkList() {
     12         this.root = new Node("head");
     13         System.out.println("创建了带头指针的链表");
     14     }
     15 
     16     public MyLinkList(Object data) {
     17         if (data == null)
     18             System.out.println("参数错误");
     19         this.root = new Node(data);
     20         this.size++;
     21         System.out.println("创建成功" + data);
     22     }
     23 
     24     // 是否是空表
     25     public boolean isEmpty() {
     26         return this.size == 0;
     27     }
     28 
     29     // 返回长度
     30     public int size() {
     31         return this.size;
     32     }
     33     
     34     // 清空链表
     35     public void clear(){
     36         this.root = null;
     37         this.size = 0;
     38     }
     39 
     40     // 判断两个链表是否相等
     41     public boolean equals(Object obj){
     42         // 常规判断
     43         if(obj == null)
     44             return false;
     45         if(obj == this)
     46             return true;
     47         
     48         // 是MyLinkList类
     49         if(obj instanceof MyLinkList){
     50             MyLinkList linkList = (MyLinkList)obj;
     51             
     52             // 根结点相同
     53             if(!this.root.data.equals(linkList.root.data)){
     54                 System.out.println("根节点不相同");
     55                 return false;
     56             }
     57             // 长度相同
     58             if(this.size != linkList.size) {
     59                 System.out.println("长度不同");
     60                 return false;
     61             }
     62             
     63             // 各个结点相同
     64             if(this.size==1){ // 只含有根结点
     65                 return true;
     66             }
     67             return this.root.next.equals(linkList.root.next);
     68         }
     69         
     70         // 不是MyLinkList类
     71         return false;
     72             
     73     }
     74 
     75     // 添加单个数据
     76     public boolean addData(Object data) {
     77         if (data == null) {
     78             System.out.println("参数错误");
     79             return false;
     80         }
     81 
     82         // 把data封装成带指针域的结点
     83         Node node = new Node(data);
     84 
     85         if (this.root.next == null)
     86             this.root.next = node;
     87         else
     88             this.root.next.addNode(node);
     89         System.out.println("添加成功" + data);
     90         this.size++;
     91         return true;
     92     }
     93 
     94     // 添加多个数据
     95     public boolean addDatas(Object[] datas) {
     96         if (datas == null) {
     97             System.out.println("参数错误");
     98             return false;
     99         }
    100 
    101         // 循环添加结点
    102         for (int index = 0; index < datas.length; ++index) {
    103             Node data = new Node(datas[index]);// 封装结点
    104             this.root.addNode(data);
    105             this.size++;
    106         }
    107         return true;
    108     }
    109 
    110     // 查找数据是否存在
    111     public boolean contains(Object data) {
    112         if (data == null || this.isEmpty())
    113             return false;
    114         return this.root.containsNode(data);
    115     }
    116 
    117     // 查找指定位置下的数据
    118     public Object get(int index) {
    119         // 参数错误
    120         if (this.isEmpty() || index < 0 || index > this.size)
    121             return null;
    122 
    123         if (this.root.data.equals("head")) { // 带头指针
    124             if (index == 1) // 返回第一个有效数据
    125                 return this.root.next.data;
    126             else {
    127                 this.index = 0;
    128                 return this.root.next.getNode(index);
    129             }
    130         } else { // 不带头指针
    131             if (index == 1) // 返回第一个有效数据
    132                 return this.root.data;
    133             else {
    134                 this.index = 1;
    135                 return this.root.next.getNode(index);
    136             }
    137 
    138         }
    139     }
    140 
    141     // 删除数据
    142     public boolean deleteData(Object data) {
    143         if (data == null || this.isEmpty()) {
    144             return false;
    145         }
    146         // 是根结点
    147         if (this.root.data.equals(data)) {
    148             this.root = this.root.next;
    149             this.size--;
    150             return true;
    151         }
    152 
    153         // 不是根节点
    154         else
    155             return this.root.deleteNode(data);
    156     }
    157 
    158     // 打印所有数据
    159     public void print() {
    160         if (this.isEmpty())
    161             System.out.print("空表--------");
    162         else
    163             this.root.printNode();
    164         System.out.println("");
    165     }
    166 
    167     // 返回数组数据
    168     public Object[] toArray() {
    169         if (this.isEmpty())
    170             return null;
    171 
    172         // 数组保存
    173         this.index = 0; // 数组下标
    174         if (this.root.data.equals("head")) // 链表带头指针
    175             reData = new Object[++this.size];
    176         else
    177             reData = new Object[this.size];
    178         this.root.toArray();
    179         return reData;
    180     }
    181 
    182     // 结点类(内部)
    183     class Node {
    184         Object data; // 数据域
    185         Node next; // 指针域
    186 
    187         // 构造方法
    188         public Node(Object data) {
    189             this.data = data;
    190         }
    191 
    192         // 添加结点
    193         public void addNode(Node node) {
    194             if (this.next == null)
    195                 this.next = node;
    196             else
    197                 this.next.addNode(node);
    198         }
    199 
    200         // 打印结点数据
    201         public void printNode() {
    202             System.out.print(this.data + " ");
    203             if (this.next != null)
    204                 this.next.printNode();
    205         }
    206 
    207         // 删除结点
    208         public boolean deleteNode(Object data) {
    209             if (this.next == null) {
    210                 System.out.println("删除失败" + data);
    211                 return false;
    212             }
    213             if (this.next.data.equals(data)) {
    214                 System.out.println("删除成功" + this.next.data);
    215                 MyLinkList.this.size--;
    216                 this.next = this.next.next;
    217                 return true;
    218             }
    219             return this.next.deleteNode(data);
    220         }
    221 
    222         // 返回数组
    223         public void toArray() {
    224             MyLinkList.this.reData[MyLinkList.this.index++] = this.data;
    225             if (this.next != null)
    226                 this.next.toArray();
    227         }
    228 
    229         // 查找指定结点
    230         public Object getNode(int index) {
    231             if (++MyLinkList.this.index == index)
    232                 return this.data;
    233             return this.next.getNode(index);
    234         }
    235 
    236         // 查找结点
    237         public boolean containsNode(Object data) {
    238             if (this.data == data)
    239                 return true;
    240             if (this.next != null)
    241                 return this.next.containsNode(data);
    242             return false;
    243         }
    244         
    245         // 重写equals()
    246         public boolean equals(Node node){
    247             // 数据域是否相同
    248             if(!this.data.equals(node.data)) {
    249                 System.out.println("数据域不同this:"+this.data+" linkList:"+node.data);
    250                 return false;
    251             }
    252             // 还有下个结点
    253             if(this.next!=null)
    254                 return this.next.equals(node.next);
    255             // 没有下个结点且到目前为止所有结点数据域相同
    256             return true;
    257             
    258         }
    259     }
    260 }
    MyLinkList

    TestMyLinkList类

     1 package List;
     2 
     3 // 单向链表测试
     4 public class TestMyLinkList {
     5 
     6     public static void main(String[] args) {
     7         // 创建一个链表
     8         MyLinkList linkList = new MyLinkList(5);
     9 
    10         // 初始化一个链表
    11         for (int index = 1; index < 10; ++index) {
    12             int num = (int) (Math.random() * 11);
    13             linkList.addData(num);
    14         }
    15 
    16         // 打印链表的所有数据
    17         linkList.print();
    18 
    19         // 删除结点
    20         linkList.deleteData(5);
    21         linkList.print();
    22         linkList.deleteData(10);
    23         linkList.print();
    24 
    25         System.out.println("第2个结点数据:" + linkList.get(2));
    26         // 数组化
    27         Object[] data = new Object[linkList.size()];
    28         data = linkList.toArray();
    29         for (Object index : data)
    30             System.out.print(index + " ");
    31         System.out.println("");
    32         System.out.println("-------------------");
    33         // 创建一个链表
    34         MyLinkList linkList2 = new MyLinkList();
    35 
    36         // 待添加数据的数组
    37         Object[] datas = { 5, "123", 26 };
    38         linkList2.addDatas(datas);
    39         System.out.println("包含'5'吗" + linkList2.contains(5));
    40         linkList2.print();
    41         System.out.println("----------------------------");
    42         // 创建一个链表
    43         MyLinkList linkList1 = new MyLinkList();
    44         linkList1.addDatas(datas);
    45         linkList1.print();
    46         System.out.println("是否相等"+linkList2.equals(linkList1));
    47     }
    48 
    49 }
    TestMyLinkList

    打印

     1 添加成功5
     2 添加成功1
     3 添加成功6
     4 添加成功6
     5 添加成功6
     6 添加成功1
     7 添加成功5
     8 添加成功2
     9 添加成功10
    10 5 5 1 6 6 6 1 5 2 10 
    11 5 1 6 6 6 1 5 2 10 
    12 删除成功10
    13 5 1 6 6 6 1 5 2 
    14 第2个结点数据:1
    15 5 1 6 6 6 1 5 2 
    16 -------------------
    17 包含'5'吗true
    18 head 5 123 26 
    19 ----------------------------
    20 head 5 123 26 
    21 是否相等true
    TestMyLinkList-console

    总结:1.避免空指针异常(NullPointException):先判断引用是否为null,后使用。

    参考:https://www.cnblogs.com/dolphin0520/p/3811445.html

    2018-7-19

    二、双向链表(循环、头插法)

    DoubleLink类

      1 package List;
      2 
      3 // 双向链表(循坏、头插法)
      4 public class DoubleLink {
      5     private Node root; // 表头
      6     private int size; // 长度
      7 
      8     // 结点类
      9     private class Node {
     10         Object data; // 数据域
     11         Node prev; // 前趋
     12         Node next; // 后继
     13 
     14         // 构造方法
     15         public Node(Object data, Node prev, Node next) {
     16             this.data = data;
     17             this.prev = prev;
     18             this.next = next;
     19         }
     20 
     21         public Node(Object data) {
     22             this.data = data;
     23         }
     24     }
     25 
     26     // 构造方法
     27     public DoubleLink() {
     28         this.root = new Node(null, null, null);
     29         this.root.prev = this.root.next = this.root;
     30         this.size = 0;
     31     }
     32 
     33     // 是否是空表
     34     public boolean isEmpty() {
     35         return this.size == 0;
     36     }
     37 
     38     // 返回长度
     39     public int size() {
     40         return this.size;
     41     }
     42 
     43     // 添加数据
     44     public boolean addData(Object data) {
     45         // 空引用
     46         if (data == null)
     47             return false;
     48 
     49         this.size++; // 增加长度
     50         Node node = new Node(data); // 封装结点
     51         // 添加结点
     52 
     53         if (this.isEmpty()) {
     54             this.root.next = node;
     55             this.root.prev = node;
     56 
     57             node.next = this.root;
     58             node.prev = this.root;
     59             return true;
     60         }
     61 
     62         // 头插法
     63         node.next = this.root.next; // 将新结点的后继指向头结点的后继
     64         node.prev = this.root; // 将新结点的前驱指向头结点
     65         this.root.next.prev = node; // 头结点的后继结点的前驱指向新结点
     66         this.root.next = node; // 头结点的后继节点指向新结点
     67         return true;
     68     }
     69 
     70     // 查找第index结点
     71     private Node getNode(int index) {
     72         Node oldNode = this.root;
     73         int foot = 0; // 脚标
     74         if (index <= this.size / 2) { // 正查找
     75             System.out.print("正查");
     76             while (true) {
     77                 if (foot++ == index)
     78                     break;
     79                 oldNode = oldNode.next;
     80             }
     81         } else {
     82             int LIndex = this.size + 1 - index;
     83             System.out.print("反查");
     84             while (true) {
     85                 if (foot++ == LIndex)
     86                     break;
     87                 oldNode = oldNode.prev;
     88             }
     89         }
     90         System.out.print(oldNode.data);
     91         return oldNode;
     92     }
     93 
     94     // 查找结点
     95     private Node getNode(Object data) {
     96         Node oldNode = this.root.next;
     97         while (true) {
     98             if (oldNode.data.equals(data))
     99                 return oldNode;
    100             if (oldNode.next.data == null)
    101                 return null;
    102             oldNode = oldNode.next;
    103         }
    104 
    105     }
    106 
    107     // 删除结点
    108     private void removeNode(Node node) {
    109         node.next.prev = node.prev; // 结点的后继结点的前驱指向结点的前驱
    110         node.prev.next = node.next; // 结点的前驱结点的后继指向结点的后继
    111         node = null;
    112     }
    113 
    114     // 前插法
    115     private boolean addNode(Node oldNode, Node newNode) {
    116         oldNode.prev.next = newNode;
    117         newNode.prev = oldNode.prev;
    118         oldNode.prev = newNode;
    119         newNode.next = oldNode;
    120         return true;
    121     }
    122 
    123     // 在index结点前插入新结点
    124     public boolean addData(Object data, int index) {
    125         if (data == null)
    126             return false;
    127         if (index <= 0 || index > this.size)
    128             return false;
    129 
    130         Node newNode = new Node(data); // 封装结点
    131 
    132         // 查找结点
    133         Node oldNode = getNode(index);
    134         this.size++; // 增加长度
    135         // 更改指针域
    136         return addNode(oldNode, newNode);
    137     }
    138 
    139     // 得到第index个结点的数据
    140     public Object get(int index) {
    141         if (this.isEmpty())
    142             return null;
    143         if (index <= 0 || index > this.size)
    144             return null;
    145 
    146         // 查找结点
    147         return getNode(index).data;
    148     }
    149 
    150     // 查找数据是否存在
    151     public boolean contains(Object data) {
    152         if (data == null)
    153             return false;
    154         if (this.isEmpty())
    155             return false;
    156 
    157         // 查找结点
    158         if (getNode(data) == null)
    159             return false;
    160         else
    161             return true;
    162     }
    163 
    164     // 删除指定数据
    165     public boolean remove(Object data) {
    166         if (data == null)
    167             return false;
    168         if (this.isEmpty())
    169             return false;
    170 
    171         // 查找结点
    172         Node node = getNode(data);
    173         if (node == null)
    174             return false;
    175 
    176         // 删除结点
    177         removeNode(node);
    178         this.size--; // 长度减一
    179         return true;
    180     }
    181 
    182     // 删除第index个结点
    183     public boolean removeIndex(int index) {
    184         if (this.isEmpty())
    185             return false;
    186         if (index <= 0 || index > this.size)
    187             return false;
    188 
    189         // 查找结点
    190         Node node = getNode(index);
    191         // 删除结点
    192         removeNode(node);
    193         this.size--; // 长度减一
    194         return true;
    195     }
    196 
    197     // equals()
    198     public boolean equals(Object obj) {
    199         if (obj == null)
    200             return false;
    201 
    202         // 是DoubleLink类
    203         if (obj instanceof DoubleLink) {
    204             // 对象下转型为DoubleLink类
    205             DoubleLink link = (DoubleLink) obj;
    206 
    207             // 比较长度
    208             if (this.size != link.size)
    209                 return false;
    210 
    211             Node thisNode = this.root.next;
    212             Node linkNode = link.root.next;
    213             // 比较每个结点的后继的数据域是否相同
    214             while (true) {
    215                 if (thisNode.data == null) // 只有头结点数据域为空
    216                     break;
    217 
    218                 if (!thisNode.data.equals(linkNode.data)) // 结点数据域不相同
    219                     return false;
    220 
    221                 thisNode = thisNode.next;
    222                 linkNode = linkNode.next;
    223             }
    224         }
    225         return true;
    226     }
    227 
    228     // 获得所有数据
    229     public Object[] toArray() {
    230         if (isEmpty())
    231             return null;
    232 
    233         Object[] datas = new Object[this.size];
    234         int index = 0; // 数组脚标
    235         Node node = this.root.prev; // 当前结点
    236         while (true) {
    237             if (node.data == null) // 只有头结点数据域为空
    238                 break;
    239             datas[index++] = node.data;
    240             node = node.prev;
    241         }
    242 
    243         return datas;
    244     }
    245 
    246     // 打印信息
    247     public void print() {
    248         if (isEmpty())
    249             System.out.println("空表");
    250 
    251         else {
    252             Node node = this.root.next;
    253             while (true) {
    254                 if (node.data == null)
    255                     break;
    256                 System.out.print(node.data + " ");
    257                 node = node.next;
    258             }
    259             System.out.println();
    260         }
    261     }
    262 
    263 }
    DoubleLink

    TestDoubleLink类

     1 package List;
     2 
     3 // 双向链表测试类
     4 public class TestDoubleLink {
     5 
     6     public static void main(String[] args) {
     7         // TODO Auto-generated method stub
     8 
     9         // 初始化一个双向链表
    10         DoubleLink link1 = new DoubleLink();
    11         link1.print();
    12         
    13         // 添加数据
    14         System.out.println("头插法添加10 5 12 null");
    15         System.out.print("添加结果:"+link1.addData(10)+" ");
    16         System.out.print(link1.addData(5)+" ");
    17         System.out.print(link1.addData(12)+" ");
    18         System.out.println(link1.addData(null));
    19         link1.print();
    20         
    21         // 在指定位置前插入数据
    22         System.out.println("
    在第2为前插入一个40,在第4位前插入一个50");
    23         System.out.println("插入结果:"+link1.addData(40, 2)+"  "+link1.addData(50,4));
    24         link1.print();
    25         
    26         // 检查是否指定数据
    27         System.out.println("
    检查是否含有数据:50 30");
    28         System.out.println("检查结果:"+link1.contains(50)+"  "+link1.contains(30));
    29         link1.print();
    30         
    31         // 删除指定数据
    32         System.out.println("
    删除指定数据:50 0");
    33         System.out.println("删除结果:"+link1.remove(50)+" "+link1.remove(0));
    34         link1.print();
    35         
    36         // 删除指定位置上的数据
    37         System.out.println("
    删除指定位置上的数据:第3位 第10位");
    38         System.out.println("删除结果:"+link1.removeIndex(3)+" "+link1.removeIndex(10));
    39         link1.print();
    40         
    41         
    42         // 比较两个链表是否相同
    43         DoubleLink link2 = new DoubleLink();
    44         DoubleLink link3 = new DoubleLink();
    45         link2.addData(10);
    46         link2.addData(40);
    47         link2.addData(12);
    48         link3.addData(12);
    49         link3.addData(40);
    50         link3.addData(10);
    51         System.out.println("
    比较两个链表是否相同");
    52         System.out.print("link1:");
    53         link1.print();
    54         System.out.print("link2:");
    55         link2.print();
    56         System.out.print("link3:");
    57         link3.print();
    58         System.out.println("link1和link2: "+link1.equals(link2)+"
    link1和link3:"+link1.equals(link3)+"
    link1和null:"+link1.equals(null));
    59 
    60     }
    61 
    62 }
    TestDoubleLink

    打印

     1 空表
     2 头插法添加10 5 12 null
     3 添加结果:true true true false
     4 12 5 10 
     5 
     6 在第2为前插入一个40,在第4位前插入一个50
     7 反查反查插入结果:true  true
     8 12 40 5 50 10 
     9 
    10 检查是否含有数据:50 30
    11 检查结果:true  false
    12 12 40 5 50 10 
    13 
    14 删除指定数据:50 0
    15 删除结果:true false
    16 12 40 5 10 
    17 
    18 删除指定位置上的数据:第3位 第10位
    19 反查删除结果:true false
    20 12 40 10 
    21 
    22 比较两个链表是否相同
    23 link1:12 40 10 
    24 link2:12 40 10 
    25 link3:10 40 12 
    26 link1和link2: true
    27 link1和link3:false
    28 link1和null:false
    TestDoubleLink-console

    总结:1.避免查找错误:先执行查找函数,再改变链表长度。

    参考:https://www.cnblogs.com/skywang12345/p/3561803.html

    2018-7-20

  • 相关阅读:
    mysql启动时报错:Starting MySQL... ERROR! The server quit without updating PID file (/opt/mysql/data/mysql.pid)
    awk技巧【转】
    在分析nginx日志时常用命令总结【转】
    mybatis 详解(八)------ 懒加载
    mybatis 详解(七)------一对一、一对多、多对多
    mybatis 详解(六)------通过mapper接口加载映射文件
    mybatis 详解(五)------动态SQL
    mybatis 详解(四)------properties以及别名定义
    mybatis 详解(三)------入门实例(基于注解)
    mybatis 详解(二)------入门实例(基于XML)
  • 原文地址:https://www.cnblogs.com/xiaoxu-xmy/p/9337161.html
Copyright © 2011-2022 走看看