集合,链表的意义

链表是一种重要的数据结构,在程序设计中占有很重要的地位。C语言和C++语言中是用指针来实现链表结构的,由于Java语言不提供指针,所以有人认为在Java语言中不能实现链表,其实不然,Java语言比C和C++更容易实现链表结构。Java语言中的对象引用实际上是一个指针(本文中的指针均为概念上的意义,而非语言提供的数据类型),所以我们可以编写这样的类来实现链表中的结点。

  class Node
  {
  Object data;
  Node next;//指向下一个结点
  }

  将数据域定义成Object类是因为Object类是广义超类,任何类对象都可以给其赋值,增加了代码的通用性。为了使链表可以被访问还需要定义一个表头,表头必须包含指向第一个结点的指针和指向当前结点的指针。为了便于在链表尾部增加结点,还可以增加一指向链表尾部的指针,另外还可以用一个域来表示链表的大小,当调用者想得到链表的大小时,不必遍历整个链表。下图是这种链表的示意图:

  链表的数据结构

  我们可以用类List来实现链表结构,用变量Head、Tail、Length、Pointer来实现表头。存储当前结点的指针时有一定的技巧,Pointer并非存储指向当前结点的指针,而是存储指向它的前趋结点的指针,当其值为null时表示当前结点是第一个结点。那么为什么要这样做呢?这是因为当删除当前结点后仍需保证剩下的结点构成链表,如果Pointer指向当前结点,则会给操作带来很大困难。那么如何得到当前结点呢,我们定义了一个方法cursor(),返回值是指向当前结点的指针。类List还定义了一些方法来实现对链表的基本操作,通过运用这些基本操作我们可以对链表进行各种操作。例如reset()方法使第一个结点成为当前结点。insert(Object d)方法在当前结点前插入一个结点,并使其成为当前结点。remove()方法删除当前结点同时返回其内容,并使其后继结点成为当前结点,如果删除的是最后一个结点,则第一个结点变为当前结点。

  链表类List的源代码如下:

  import java.io.*;
  public class List
  {
  /*用变量来实现表头*/
  private Node
Head=null;
  private Node
Tail=null;
  private Node
Pointer=null;
  private int
Length=0;
  public void
deleteAll()
  /*清空整个链表*/
  {
  Head=null;
  Tail=null;
  Pointer=null;
  Length=0;
  }
  public void reset()
  /*链表复位,使第一个结点成为当前结点*/
  {
  Pointer=null;
  }
  public boolean
isEmpty()
  /*判断链表是否为空*/
  {
  return(Length==0);
  }
  public boolean
isEnd()
  /*判断当前结点是否为最后一个结点*/
  {
  if(Length==0)
   throw new
java.lang.NullPointerException();
  else if(Length==1)
   return true;
  else
   return(cursor()==Tail);
  }
  public Object
nextNode()
  /*返回当前结点的下一个结点的值,并使其成为当前结点*/
  {
  if(Length==1)
   throw new
java.util.NoSuchElementException();
  else if(Length==0)
   throw new
java.lang.NullPointerException();
  else
  {
   Node temp=cursor();
   Pointer=temp;
   if(temp!=Tail)
    return(temp.next.data);
   else
    throw new java.util.NoSuchElementException();
  }
  }
  public Object
currentNode()
  /*返回当前结点的值*/
  {
  Node temp=cursor();
  return temp.data;
  }
  
  public void
insert(Object d)
  /*在当前结点前插入一个结点,并使其成为当前结点*/
  {
  Node e=new Node(d);
  if(Length==0)
  {
   Tail=e;
   Head=e;
  }
  else
  {
   Node temp=cursor();
   e.next=temp;
   if(Pointer==null)
    Head=e;
   else
    Pointer.next=e;
  }
  Length++;
  }
  public int size()
  /*返回链表的大小*/
  {
  return (Length);
  }
  public Object
remove()
  /*将当前结点移出链表,下一个结点成为当前结点,如果移出的结点是最后一个结点,则第一个结点成为当前结点*/
  {
  Object temp;
  if(Length==0)
   throw new
java.util.NoSuchElementException();
  else if(Length==1)
  {
   temp=Head.data;
   deleteAll();
  }
  else
  {
   Node cur=cursor();
   temp=cur.data;
   if(cur==Head)
    Head=cur.next;
   else if(cur==Tail)
   {
    Pointer.next=null;
    Tail=Pointer;
    reset();
   }
   else
    Pointer.next=cur.next;
    Length--;
  }
  return temp;
  }
  private Node
cursor()
  /*返回当前结点的指针*/
  {
  if(Head==null)
   throw new
java.lang.NullPointerException();
  else
if(Pointer==null)
   return Head;
  else
   return
Pointer.next;
  }
  public static void
main(String[] args)
  /*链表的简单应用举例*/
  {
  List a=new List ();
  for(int
i=1;i<=10;i++)
   a.insert(new
Integer(i));
   System.out.println(a.currentNode());
   while(!a.isEnd())
    System.out.println(a.nextNode());
    a.reset();
    while(!a.isEnd())
    {
     a.remove();
    }
    a.remove();
    a.reset();
    if(a.isEmpty())
     System.out.println("There
is no Node in List \n");
     System.in.println("You
can press return to quit\n");
    try
    {
     System.in.read();
     //确保用户看清程序运行结果
    }
    catch(IOException
e)
    {}
   }
  }
  class Node
  /*构成链表的结点定义*/
  {
   Object data;
   Node next;
   Node(Object d)
   {
    data=d;
    next=null;
   }
  }

  读者还可以根据实际需要定义新的方法来对链表进行操作。双向链表可以用类似的方法实现只是结点的类增加了一个指向前趋结点的指针。

  可以用这样的代码来实现:

  class Node
  {
  Object data;
  Node next;
  Node previous;
  Node(Object d)
  {
  data=d;
  next=null;
  previous=null;
  }
  }

  当然,双向链表基本操作的实现略有不同。链表和双向链表的实现方法,也可以用在堆栈和队列的实现中,这里就不再多写了,有兴趣的读者可以将List类的代码稍加改动即可。

时间: 2024-08-04 01:20:26

集合,链表的意义的相关文章

Java学习分享--&gt;集合--&gt;链表

链表是一个有序集合,它将每个对象存放在独立的结点中,每个结点还存放着下一个结点的引用.在Java中由于链表是双向链接的,每个结点还存放着前一个结点的引用. (图片引自Java核心技术 卷1 基础知识) 删除链表中间的一个元素,只需要更新被删除元素附近的结点.假设我们有三个结点,删除第二个结点后,第一个结点将原本存放第二个结点的引用更新为第三个结点的引用(这里对应我们前面提到的"每个结点还存放着下一个结点的引用"),而第三个结点将原本存放第二个结点的引用更新为第一个结点的引用(这里对应我

初识java集合——链表

* 链表中的每个节点,存放着上一个节点的引用和下一个节点的引用 * 相对于泛型集合,链表是一个有序集合,每个对象的位置十分的重要 * 链表的add默认也是添加到尾部的 * * 链表的添加删除操作往往借助迭代器来完成,参见IteratorIntro * * 对于链表的遍历,绝对不要使用(代码区-1)的方式,例如get(3),要从头开 * 始到3的索引,get(7),又得从头开始到7的位置,效率非常的低. * 因为LinkedList对象不做任何缓存位置信息操作 * //代码区-1 for( int

java中的集合链表

java中的集合类有很多种,每个都有自己的一些特点,推荐你专门在这方面研究一下,比方Vector,ArrayList,,LinkedList,Hashtable等,其中你问到的链表,是不是指LinkedList呢?LinkedList是集合类的一种,和其它集合类一样都用于存放未知内容和未知长度的数据或者说对象.由于LinkedList的内部实现是采用链表结构,所以它就取名为LinkedList当然ArrayList的内部实现是采用数组结构,所以它就取名为ArrayList,呵呵,很好理解吧. 它

C#并行编程-并发集合

原文:C#并行编程-并发集合 菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 背景 基于任务的程序设计.命令式数据并行和任务并行都要求能够支持并发更新的数组.列表和集合. 在.NET Framework 4 以前,为了让共享的数组.列表和集合能够被多个线程更新,需要添加复杂的代码来同步这些更新操作. 如您需要编写一个并行循环,这个循环以无序的方式向一个共享集合中添加元素,那么必须加入一个同步机制来保证这是一个线程安全的集合. System.Collenctions

重新温习链表

链表有两种实现方案,一是有头节点,二是无头节点. 方案一中有头节点,指向头节点的指针叫做头指针,但是头节点只是为了操作统一方便,头节点的数据域为空或者存储链表的长度等信息,只有头节点的链表叫做空链表. 方案二中没有头节点,空链表的意义为头指针指向NULL, 方案一源码 // 此头文件包含链表的基本操作 // 类型:单链表 #include<stdlib.h> #include<stdio.h> #include<malloc.h> typedef int ElemTyp

Qlikview集合分析

集合分析 集合可用于聚合函数.聚合函数一般用于聚合当前选择范围定义的可能记录的集合.但替代记录集合可由集合表达式定义.因此,集合在概念上与选择范围类似. 在使用中,集合表达式时总是以波形括号开始和结束,例如:{BM01}. 集合标识符 可以用一个常数表示记录集 1.记录集表示应用程序中所有记录的完全集合. 符号 $ 代表当前选择项范围内的记录.因此,陈述集合表达式 {$} 与不陈述集合表达式的意义等同.更有趣的是,{1-$}定义了当前选择项的反置,即指未包括在当前选择项中的所有数据. 后退/前进

集合与数组互转

一.集合转数组 以ArrayList集合为例,使用该集合的一个成员方法toArray(),可以将一个集合对象转化为一个数组.如下所示: 1 void listToArray(){ 2 List<String> list=new ArrayList<>();//创建一个集合对象 3 list.add("a");//向集合对象里添加元素 4 list.add("b"); 5 list.add("c"); 6 System.ou

python学习04-数据类型(元组、字典、集合)

一.基本数据类型--元组   元组:是一种与列表非常相似的数据类型.但是它一旦创建便不能再修改,所以又叫只读列表. 定义:与列表类似,只不过[]改成() 特性: 可存放多个值(可以存放复杂数据类型) 不可变(显式地告诉别人此处数据不可修改,常用于数据库连接配置信息等) 按照从左到右的顺序定义元组元素,下标从0开始顺序访问,有序 元组本身不可变,如果元组中还包含其它可变元素,这些可变元素可以改变.(比如列表等) 元组常用操作 创建 ages = (11, 22, 33, 44, 55) #或 ag

第二章 集合 字符编码

集合 定义:有一个或多个确定的元素所构成的整体叫做集合. 特征: 1. 确定性(元素必须可hsah) 2. 互异性(去重) 3. 无序性(集合中的元素没有先后之分) 集合存在的意义就在于去重和关系运算 集合的创建: s = {} 创建一个字典 s = {1} 创建一个集合 集合的关系运算 交集 取出两个集合中共有的元素 s.intersection(s1) s & s1 差集 s.difference(s1) s - s1 从s中把s1中有的元素都去掉,通俗来讲就是:你有的我通通不要. 并集 s