链表 二叉树–数据结构的基本功
数据结构就是引用传递和递归数组定长的线性结构的特点,使得如果内容过多或过少都会产生内存的浪费。采用火车的车厢的问题,最好的做法就是使用一个不固定长度的数组,有多少数据就保存多少数据。类似于火车车厢。如果想去定义火车车厢,不能只保留数据,还需要一个位置指向下一个节点。 取出的方式利用递归的方式取出。递归的要有一个结束条件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]);
}
}
}