四 模拟实现单链表

单链表及其结点:

链表是一系列存储元素的单元通过指针串接起来实现的,这些单元称为结点,每个单元有两个域:

  • 值域:用于存储数据元素
  • 指针域:指向下一个具有相同结构的结点

因为只有一个指针结点,称为单链表

特点:

  •            尾结点的特征是其next引用为空
  •            链表中每个结点的next引用都相当于一个指针,指向另一个结点。借助next可完成链表首结点移动到尾结点。
  •            单链表中通常用head引用来指向链表的首结点,由head引用可以完成对整个链表中所有结点的访问。
  •            单链表只能通过前驱结点找到后续结点,而无法从后续结点找到前驱结点。

与数组相似,单链表中的结点也具有一个线性次序,即如果节点p的next引用指向结点S,则p就是S的直接前驱,反之是直接后继。

 

单链表的查询、添加、删除操作分析:

查询操作:在单链表中查找是否包含某个数据元素e,只能从链表的首结点开始,通过每个结点的next引用来依次访问链表中的每个结点,完成相应的查找操作。

1 起始条件:p=head;

2 结束条件:找到e.equals(p.getData())==true

                    未找到:p==null

3 p指向下一个结点:p=p.getNext();

缺点:逐个比较,频繁移动指针,导致效率低下

如果查询第i个元素的值,同样无法直接定位,只能从首结点开始逐个移动到第i个结点,效率同样低下。

添加操作

在单链表中元素的插入,是通过在链表中插入数据元素所属的结点来完成的。

对于链表的不同位置,插入的过程会有细微的差别。中间,末尾的添加过程是一样的,关键是首部添加,会有不同。

首部添加会改变整个单链表的起始终点。

1 指明新结点的后继

2 指明新结点的前驱

 

添加结点不需要移动元素,只需要修改元素的指针,效率高。

删除操作:改变指针,使该结点的前驱指向下个结点

在用单链表实现线性表的时候,为了使程序更加简洁,我们通常在单链表的最前面添加一个头结点。

头结点值域为空,next指向线性表中0号元素所在结点,值域为null。可以对空表、非空表首元结点进行统一处理,简化代码,很常用。

 

 

代码实现:

1 新建Node类,内有data和next属性,分别代表值域和指针域;

package com.lt.datastructure.linetable;
/**
 * 单链表的结点
 */
public class Node {
    Object data;//要存储的数据
    Node next;//指向下一个元素   
    public Node() 
    {
     }
    
    public Node(Object data) 
    {    
         this.data = data;
     }
    
   public Node(Object data, Node next) 
   {
        super();
        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;
} 
}

2  实现简单的功能

 1 package com.lt.datastructure.linetable;
 2 
 3 public class SingleLinkedList implements List{
 4     
 5     private Node head = new Node();//头结点,不存储数据,为了编程方便
 6     
 7     private int size; //一共有几个结点
 8     
 9 
10     public int size() {
11         return size;
12     }
13 
14     @Override
15     public Object get(int i) {
16         //和顺序表不一样,不能通过索引计算定位,需要从头结点逐个查找
17         Node p = head;
18         for(int j = 0 ; j<=i;j++){
19             p = p.next;
20             //p.next就是head.next,head.next指向0结点的地址
21 //            p=0时,head.next赋给p,p指向0结点的地址,p=i时,p指向i的地址
22         }
23         return p.data;//得到i位置的数据
24     }
25     
26     @Override
27     public void add(int i, Object e) {
28         //p是头结点
29         Node p = head;
30         for(int j=0;j<i;j++){
31         //j=0,p.next从head变为head.next指向0结点地址,p是0结点,j=i-1,p指向i-1的地址,p是i-1结点
32         p = p.next; 
33         }                             
34         Node newNode = new Node();
35         newNode.data = e;
36         newNode.next = p.next; // 此处p.next指向i结点,newNode的后驱指向i结点
37         p.next = newNode;    //原本指向1结点的指向newNode结点的地址,newNode成功插入i结点
38         //newNode成功成为为1结点
39         size++;        
40     }
41 
42     @Override
43     public void add(Object e) {
44      this.add(size,e);        
45     }
46

 

转载于:https://www.cnblogs.com/ltfxy/p/9810909.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值