链表的概念实现

版权声明:嘻嘻嘻嘻,I see you https://blog.csdn.net/qq_38317309/article/details/85919336

链表 二叉树–数据结构的基本功
数据结构就是引用传递和递归数组定长的线性结构的特点,使得如果内容过多或过少都会产生内存的浪费。采用火车的车厢的问题,最好的做法就是使用一个不固定长度的数组,有多少数据就保存多少数据。类似于火车车厢。如果想去定义火车车厢,不能只保留数据,还需要一个位置指向下一个节点。 取出的方式利用递归的方式取出。递归的要有一个结束条件class Node{//只有node 类才能设置数据的先后关系

private Object data;//定义数组的内容,这也是真正也保存数据的地方
 private Node next;//定义下一个节点,故用Node类来定义
 public Node(Object data) {
  this.data=data;
 }
 public void setData(Object data) {
  this.data = data;
 }
 public Object getData() {
  return this.data;
 }
 public void setNext(Node next){
  this.next=next;
 }
 public Node getNext() {
  return this.next;
 }
}
public  class TestDemo{
 public static void main(String[] args) throws Exception{
  //1、封装几个节点
  Node root =new Node("车头");
  Node nd1=new Node("车厢1");
  Node nd2=new Node("车厢2");
  Node nd3=new Node("车厢3");
  //设置节点关系
  root.setNext(nd1);//把车头和车厢联结起来
  nd1.setNext(nd2);//联结1车和2车
  nd2.setNext(nd3);//联结2车和3车 但是最后一个车厢没有连接
  //把火车头拉出来,执行输出
  print(root);
 }
 //找一个输出条件
 public static void print(Node node){
  if(node!=null) {
   System.out.println(node.getData());
   print(node.getNext());//
  }
  
 }
}

这就是链表的基本模样。结论就是,在链表的实现过程中,Node 的核心作用就是保存数据以及连接节点。但是以上的代码,主方法需要自己进行节点的连接。所谓的链表就是需要一个单独的类,以这种link的方法,实现数据保存和关系处理
需要一个计数的统计操作。是在Link 类中追加一个统计个数的属性(方法)初始值为count=0,每次追加的过程中需要进行一个个数的累加

代码实现

class Link {
 private class Node {// 只有node 类才能设置数据的先后关系
  private Object data;// 定义数组的内容,这也是真正也保存数据的地方
  private Node next;// 定义下一个节点,故用Node类来定义  public Node(Object data) {
   this.data = data;
  }  public void setNext(Node next) {
   this.next = next;
  }  /**
   * 第一次调用 this=Link.root 第二次调用 this=Link.root.next 第三次调用 this=Link.root.next
   */
  public void addNode(Node newNode) {
   if (this.next == null) {// 下一个为空. 也是终点,只有找到下一个节点为空(null)的时候,才结束。
    this.next = newNode;
   } else {// 下一个不为空
    this.next.addNode(newNode);
   }
  }
 } private int count = 0;// 当前的保存个数
 private Node root;// 没有根节点就没有办法进行数据的保存 public void add(Object data) {
  if (data == null) {
   return;// 不允许存放空值
  }
  Node newNode = new Node(data);// 将数据封装在Node 节点内,否则无法确定节点的先后顺序
  if (this.root == null) {// 当前根节点为空
   this.root = newNode;// 第一节点为根节点
  } else {
   this.root.setNext(newNode);
  }
  this.count++;
 } public int size() {
  return count;
 }
 public boolean isEmpty() {
  return this.root==null&&this.count==0;
 }
}public class TestDemo {
 public static void main(String[] args) throws Exception {
  Link all = new Link();
  all.add("hello");
  all.add("world");
  all.add("mldn");
  System.out.println(all.size()); }
}

取得全部数据public Object[] toArray() 这个方法返回的是一个数组,是一个动态对象数组。要实现数组的返回,首先要开辟一个数组,而此时,数组的长度也就是刚刚写过的“count”值,数组内容应该将节点内的数据取出链表返回toArray()一个是数据内容,一个是next数组长度就等于count,链表数据与返回数据。考虑 foot 值是放在Link 类中,还是Node 中?在Node 类中处理数据数据的存储和返回,是链表使用最多的功能

class Link {
 private class Node {// 只有node 类才能设置数据的先后关系
  private Object data;// 定义数组的内容,这也是真正也保存数据的地方
  private Node next;// 定义下一个节点,故用Node类来定义  public Node(Object data) {
   this.data = data;
  }  public void setNext(Node next) {
   this.next = next;
  }  /**
   * 第一次调用 this=Link.root 第二次调用 this=Link.root.next 第三次调用 this=Link.root.next
   */
  public void addNode(Node newNode) {
   if (this.next == null) {// 下一个为空. 也是终点,只有找到下一个节点为空(null)的时候,才结束。
    this.next = newNode;
   } else {// 下一个不为空
    this.next.addNode(newNode);
   }
  }
  // 第一次调用,thiS=Link.root
  //第二次调用 this=Link.root.next
  public void toArrayNode() {
   Link.this.retData[Link.this.foot++]=this.data;//为输出数组的按照角标赋值
   if(this.next!=null) {
    this.next.toArrayNode();
   }
  }
 }
//-----------------link类定义---------------------------------
 private Object[] retData;//返回类型
 private int foot;//返回的角标
 private int count = 0;// 当前的保存个数
 private Node root;// 没有根节点就没有办法进行数据的保存 public void add(Object data) {
  if (data == null) {
   return;// 不允许存放空值
  }
  Node newNode = new Node(data);// 将数据封装在Node 节点内,否则无法确定节点的先后顺序
  if (this.root == null) {// 当前根节点为空
   this.root = newNode;// 第一节点为根节点
  } else {
   this.root.addNode(newNode);
     }
  this.count++;
 } public int size() {
  return count;
 }
 public boolean isEmpty() {
  return this.root==null&&this.count==0;
 }
 public Object[] toArray(){
  if(this.count==0) {
   return null;//现在,链表中存在有数据,则避开指定长度的数组,该数组要交给Node类进行处理
  }
  this.retData=new Object[this.count];
  this.foot=0;//角标从零开始操作。
  this.root.toArrayNode();//将数据处理交给Node类完成
  return this.retData;
 }
}public class TestDemo {
 public static void main(String[] args) throws Exception {
  Link all = new Link();
  all.add("hello");
  all.add("world");
  all.add("mldn");
  Object result[]=all.toArray();
  for(int x=0;x<result.length;x++) {
   System.out.println(result[x]);
  }
 }
}

判断数据是否妇女在public object boolean contains(Object data)链表中存在许多数据,如果要判断,数据是否存在于链表中,则需要该方法。1、判断链表是否有数据。2、链表非空的时候,进行一次的递归判断,考虑到标准化问题,需要equals()方法支持。在Node类中,追加Contains 的查找使用任何情况下都要用root 首先调用。
增添一个方法containsNode 在Node类中

public boolean containsNode(Object search) {
   if(search.equals(this.data)) {//相等
    return true;
   }else {
    if(next!=null) {//当前节点后还有其他节点
     return this.next.containsNode(search);
    }else {//后面没有其他节点了
     return false;
    }
   }
  }

同时在Link类中补上contains 方法,为Boolaen类,保证数据的合法性

public boolean contains(Object search) {
  if(search==null||this.root==null) {//没有要查询的内容或链表为空
   return false;
  }
  else {
   return this.root.containsNode(search);
  }
 }
public boolean containsNode(Object search) {
   if(search.equals(this.data)) {//相等
    return true;
   }else {
    if(next!=null) {//当前节点后还有其他节点
     return this.next.containsNode(search);
    }else {//后面没有其他节点了
     return false;
    }
   }
  }
public boolean contains(Object search) {
  if(search==null||this.root==null) {//没有要查询的内容或链表为空
   return false;
  }
  else {
   return this.root.containsNode(search);
  }
 }
要用的是String类,但要是使用的是Object类,则需要复写equals()方法。class Link {
 private class Node {// 只有node 类才能设置数据的先后关系
  private Object data;// 定义数组的内容,这也是真正也保存数据的地方
  private Node next;// 定义下一个节点,故用Node类来定义  public Node(Object data) {
   this.data = data;
  }  public void setNext(Node next) {
   this.next = next;
  }  /**
   * 第一次调用 this=Link.root 第二次调用 this=Link.root.next 第三次调用 this=Link.root.next
   */
  public void addNode(Node newNode) {
   if (this.next == null) {// 下一个为空. 也是终点,只有找到下一个节点为空(null)的时候,才结束。
    this.next = newNode;
   } else {// 下一个不为空
    this.next.addNode(newNode);
   }
  }
  // 第一次调用,thiS=Link.root
  //第二次调用 this=Link.root.next
  public void toArrayNode() {
   Link.this.retData[Link.this.foot++]=this.data;//为输出数组的按照角标赋值
   if(this.next!=null) {
    this.next.toArrayNode();
   }
  }
  //第一次调用时,this=Link.root
  //第二次调用,采用this=Link.root.next
  public boolean containsNode(Object search) {
   if(search.equals(this.data)) {//相等
    return true;
   }else {
    if(next!=null) {//当前节点后还有其他节点
     return this.next.containsNode(search);
    }else {//后面没有其他节点了
     return false;
    }
   }
  }
 }
//-----------------link类定义---------------------------------
 private Object[] retData;//返回类型
 private int foot;//返回的角标
 private int count = 0;// 当前的保存个数
 private Node root;// 没有根节点就没有办法进行数据的保存 public void add(Object data) {
  if (data == null) {
   return;// 不允许存放空值
  }
  Node newNode = new Node(data);// 将数据封装在Node 节点内,否则无法确定节点的先后顺序
  if (this.root == null) {// 当前根节点为空
   this.root = newNode;// 第一节点为根节点
  } else {
   this.root.addNode(newNode);
     }
  this.count++;
 } public int size() {
  return count;
 }
 public boolean isEmpty() {
  return this.root==null&&this.count==0;
 }
 public boolean contains(Object search) {
  if(search==null||this.root==null) {//没有要查询的内容或链表为空
   return false;
  }
  else {
   return this.root.containsNode(search);
  }
 }
 public Object[] toArray(){
  if(this.count==0) {
   return null;//现在,链表中存在有数据,则避开指定长度的数组,该数组要交给Node类进行处理
  }
  this.retData=new Object[this.count];
  this.foot=0;//角标从零开始操作。
  this.root.toArrayNode();//将数据处理交给Node类完成
  return this.retData;
 }
}public class TestDemo {
 public static void main(String[] args) throws Exception {
  Link all = new Link();
  all.add("hello");
  all.add("world");
  all.add("mldn");
  Object result[]=all.toArray();
  for(int x=0;x<result.length;x++) {
   System.out.println(result[x]);
  }
  System.out.println("=======");
  System.out.println(all.contains("hello"));//判断是否存在后面的“hello"
  System.out.println(all.contains("worlls"));//判断是否存在“worlls”
 }
}

Link 类负责操纵和传递,来操纵节点Node,所有节点操纵的方法,都要封装在Node类中。通过Link来进行调用。 客户端直接调用的是Link类中的方法。

数据的删除操作

分别讨论,讨论删除根节点还是删除的不是根节点。删除根节点 在link 中判断public Object move令root 的next 指向root= root.next,等待被垃圾回收。
如果删除子节点即 删除的上一个节点.next= 删除节点.next删除后 个数减少
不要忘了,要在执行删除操作之后,对count 指数进行减减 操作。保证输出数组的数量。

class Link {
 private class Node {// 只有node 类才能设置数据的先后关系
  private Object data;// 定义数组的内容,这也是真正也保存数据的地方
  private Node next;// 定义下一个节点,故用Node类来定义  public Node(Object data) {
   this.data = data;
  }  public void setNext(Node next) {
   this.next = next;
  }  /**
   * 第一次调用 this=Link.root 第二次调用 this=Link.root.next 第三次调用 this=Link.root.next
   */
  public void addNode(Node newNode) {//处理节点关系
   if (this.next == null) {// 下一个为空. 也是终点,只有找到下一个节点为空(null)的时候,才结束。
    this.next = newNode;
   } else {// 下一个不为空
    this.next.addNode(newNode);
   }
  }  // 第一次调用,thiS=Link.root
  // 第二次调用 this=Link.root.next
  public void toArrayNode() {
   Link.this.retData[Link.this.foot++] = this.data;// 为输出数组的按照角标赋值
   if (this.next != null) {
    this.next.toArrayNode();
   }
  }  // 第一次调用时,this=Link.root
  // 第二次调用,采用this=Link.root.next
  public boolean containsNode(Object search) {
   if (search.equals(this.data)) {// 相等
    return true;
   } else {
    if (next != null) {// 当前节点后还有其他节点
     return this.next.containsNode(search);
    } else {// 后面没有其他节点了
     return false;
    }
   }
  }  public Object getNode(int index) {
   if (Link.this.foot++ == index) {
    return this.data;
   } else {
    return this.next.getNode(index);
   }
  }
  public void setNode(int index,Object newData) {
   if(Link.this.foot++==index) {//索引相同
    this.data=newData;
   }else
    if(this.next!=null) {
     this.next.setNode(index, newData);
    }
  }
  //第一次调用时 this.=Link.root.next,previous=Link.root
  //第二次调用时,this= Link.root.next.next,previous=Link.root.next
  public void removeNode(Node previous,Object data) {
   if(this.data.equals(data)) {//当前节点为要删除的节点、
    previous.next=this.next;
   }
   else {
    this.next.removeNode(this,data);
   }
  }
 }//-----------------link类定义---------------------------------
 private Node root;// 没有根节点就没有办法进行数据的保存
 private Object[] retData;// 返回类型
 private int foot;// 返回的角标
 private int count = 0;// 当前的保存个数 public void add(Object data) {
  if (data == null) {
   return;// 不允许存放空值
  }
  Node newNode = new Node(data);// 将数据封装在Node 节点内,否则无法确定节点的先后顺序
  
  if (this.root == null) {// 当前根节点为空
   this.root = newNode;// 第一节点为根节点
  } else {
   this.root.addNode(newNode);
  }
  this.count++;
 } public int size() {
  return count;
 } public boolean isEmpty() {
  return this.root == null && this.count == 0;
 } public boolean contains(Object search) {
  if (search == null || this.root == null) {// 没有要查询的内容或链表为空
   return false;
  } else {
   return this.root.containsNode(search);
  }
 } public Object[] toArray() {
  if (this.count == 0) {
   return null;// 现在,链表中存在有数据,则避开指定长度的数组,该数组要交给Node类进行处理
  }
  this.retData = new Object[this.count];
  this.foot = 0;// 角标从零开始操作。
  this.root.toArrayNode();// 将数据处理交给Node类完成
  return this.retData;
 } public Object get(int index) {
  if (index >= this.count) {// 如果index值超过了保存的个数,则返回为空
   return null;
  }
  this.foot = 0;
  return this.root.getNode(index);
 }
 
 public void set(int index,Object newData) {
  if (index >= this.count) {// 如果index值超过了保存的个数,则返回为空 ||和get方法中的前期判断条件相同,如果,超过数值的保存长度,就返回为空
   return;
  }
  this.foot =0;
  this.root.setNode(index, newData);
 }
 public void remove(Object data) {
  if(this.contains(data)) {//如果该数据存在,进行删除处理
   if(this.root.data.equals(data)) {//判断是否为根节点数据
    this.root=root.next;//根节点就指向下一个节点
   }else{//不是根节点
    
     this.root.removeNode(this.root,data);
    }
   this.count--;
   }
 }
}public class TestDemo {
 public static void main(String[] args) throws Exception {
  Link all = new Link();
  all.add("hello");
  all.add("world");
  all.add("fengshuo");
  all.set(2, "yujun");
  all.remove("yujun");
  all.remove("hello");
  Object result[] = all.toArray();
  for (int x = 0; x <result.length; x++) {
   System.out.println(result[x]);
  }
 }
}

猜你喜欢

转载自blog.csdn.net/qq_38317309/article/details/85919336