线性表

线性表的逻辑结构

  线性表(linear list)简称表,是n(n ≥ \geq 0)个数据元素的有限序列,线性表中的数据元素的个数称为线性表的长度。长度等于零的线性表称为空表,一个非空的线性表通常记为:
                          L = (a1,a2,…,an)
其中,ai( 1 ≤ i ≤ 1\leq i\leq 1in)称为数据元素,下标i表示该元素在线性表中的位置或序号,称元素ai位于表的第i个位置,或称ai是表中的第i个元素。a1称为表头元素,an称为表尾元素,任意一对相邻的数据元素ai-1和ai( 1 < i ≤ 1<i \leq 1<in)之间存在序偶关系<ai-1,ai>,且ai-1称为ai的前驱,ai称为ai-1的后继。在这个序列中,元素a1无前驱,元素an无后继,其他每个元素有且仅有一个前驱和一个后继。一个非空线性表的逻辑结构如下图所示:
在这里插入图片描述

线性表的Java接口定义

public interface ListInterface<T>{
	public void printList();             //遍历线性表
	public int length();                 //求线性表长度
	public int locate(T element);        //按值查找
	public T getElement(int i);          //按位查找
	public void insert(int i, T element);//在指定逻辑位置插入
	T delete(int i);                     //删除指定逻辑位置元素
	public boolean isEmpty();            //判断表空
}

线性表的顺序存储结构及实现

  线性表的顺序存储结构称为顺序表(sequential list)。顺序表被定义为实现ListInterface接口的Java类SequentialList,类中的成员变量将实现顺序表存储,成员函数将实现线性表的接口函数。

public class SequentialList<T> implements ListInterface<T>{
	//成员变量实现顺序表存储结构
	//成员函数实现线性表接口函数
}

顺序表的存储结构

  顺序表存储的基本思想为:用一段地址连续的存储单元依次存储线性表的数据元素,如下图所示。设顺序表的每个元素占用c个存储单元,则第i个元素的存储地址为 :
                          LOC(ai) = Loc(a1) + (i - 1) * c
在这里插入图片描述
  很容易看出,顺序表中数据元素的存储地址是其序号的线性函数,只要确定了存储顺序表的起始地址(即基地址),计算任意一个元素的存储地址的时间是相等的,具有这一特点的存储结构称为随机存取(random access)结构。
  通常用一维数组来实现顺序表,也就是把线性表中相邻的元素存储在数组中相邻的位置,从而导致数据元素的序号和存放它的数组下标之间具有一一对应的关系,如图1-1所示。在Java语言中数组的下标从0开始,而线性表中元素的序号是从1开始,因此线性表中第i个元素存储在数组中的第i-1个位置。
  数组需要分配固定长度的数组空间,因此比如确定存放线性表的数组空间的长度。因为在线性表中可以进行插入操作,所以数组的长度要大于当前线性表的长度。用LIST_SIZE表示数组的长度,用length表示线性表的长度,如图1-1所示。
在这里插入图片描述

顺序表的实现

顺序表的存储结构实现

  在SequentialList类中,通过定义泛型数组list(存储数据元素)、整型常量LIST_SIZE(定义数组的初始容量)、整型变量length(记录表长)实现顺序表存储结构的定义。在SquentialList类被实例化时,内存中将依据成员变量的定义开辟相应的存储空间。

public class SequentialList<T> implements ListInterface<T>{
	private T[] list;                        //顺序表存储
	private final static int LIST_SIZE = 100;//数组容量
	private int length;                      //线性表的长度
	//成员函数实现线性表的接口函数
}

顺序表算法

  以顺序表存储结构为基础,在SequetialList类中实现线性表基本操作(ListInterface接口中定义的函数)。

  • 顺序表初始化
    在Java语言中通过构造函数实现类的初始化。SequentialList类中定义了两个重载的构造函数,以实现空顺序表和非空顺序表的初始化。
  • 无参构造函数
    无参构造函数,初始化空表。生成一个容量为LIST_SIZE的一维泛型数组list;表长length赋值为0。算法实现如下:
public SequentialList(){
	list = (T[])(new Object[LIST_SIZE]);
	length = 0;
}
  • 顺序表的扩容函数
    顺序表的动态分配方式是在程序执行过程中通过动态存储分配,一旦数组空间占满,可以另外再分配一块更大的存储空间,用来替换原来的存储空间,从而达到扩充数组空间的目的。
private void expandCapacity(){
	T[] expandList = (T[])(new Object[list.length * 2]);//按两倍扩容
	for(int i = 0; i < list.length; i++){               //复制原有内容
		expandList[i] = list[i];
	}
	this.list = expandList;                             //扩容后引用复制
}
  • 有参构造函数
    以泛型数组为参数的构造函数初始化容量为LIST_SIZE的一维泛型数组list;当n大于LIST_SIZE时调用expandCapacity函数,生成空间加倍的空表list;表长length赋值为参数数组的长度;将参数数组中的对象依次放入list。
public SequentialList(T[] init, int n){
	list = (T[])(new Object[LIST_SIZE]);//初始化泛型数组
	if(n > LIST_SIZE){//表长越界处理
		expandCapacity();
	}
	length = n;
	for(int i = 0; i < length; i++){
		list[i] = init[i];
	}
}
  • 判断表空
    顺序表判空只需要判断长度length是否为0,为0返回true,否则返回false。算法实现如下:
public boolean isEmpty(){
	if(length == 0){
		return true;
	}
	return false;
}
  • 求顺序表的长度
    顺序表SequentialList中的length成员变量记录了顺序表的当前长度,length()函数仅需要返回length变量。算法实现如下:
public int length(){
	return length;
}
  • 遍历顺序表
    在顺序表中,遍历操作按下标依次输出各元素。算法实现如下:
public void printList(){
	if(isEmpty()) System.out.println("空表");
	for(int i = 0; i < length; i++){
		System.out.println(list[i] + " ");
	}
}
  • 按值查找
    在顺序表中实现按值查找须对顺序表中的元素依次进行比较,如果查找成功,返回元素的逻辑序号(注意不是下标),否则返回查找失败的标志0;
public int locate(T element){
	int result = 0;
	for(int i = 0; i < length; i++){
		if(list[i].equals(element)){
			result = i +1;
			break;
		}
	}
	return result;
}
  • 按位查找
    顺序表中第i个元素存储在数组下标i-1的位置,容易实现按位查找。显然,按位查找算法的时间复杂度为O(1)(随机存取)。函数getElement接受线性表中待查找的逻辑位置的参数,返回待查位的数据元素。边界情况处理:1按位查找须判断表空,抛出异常;2查找位置不合理,须抛出位置错误异常。
public T getElement(int i){
	if(isEmpty()){
		throw new RuntimeException("表空");
	}
	if(i < 1 || i > length){
		throw new RuntimeException("查找位置非法");
	}
	T element = list[i - 1];
	return element;
}
  • 插入操作
    插入操作是在表的第i( 1 ≤ i ≤ 1\leq i\leq 1in+1)个位置插入一个新元素(若值为k),使长度为n的线性表(a1, … , ai-1, ai, … , an)变成长度为n+1的线性表(a1, … , ai-1, k, ai, …, an)。插入后,元素ai-1和ai之间的逻辑关系发生了变化并且存储位置要反映这个变化。图2-1给出了顺序表在进行插入操作的前后,数据元素在存储空间中位置的变化。
    在这里插入图片描述
    注意元素的移动方向,必须从最后一个元素开始移动,直至将第i个元素后移为止,然后将新元素插入为止i处。边界情况处理:1表满时执行插入操作,须对顺序表进行扩容;2插入位置不合理,须抛出异常。
public void insert(int i, T element){
	if(this.length == this.list.length){//表长越界处理
		expandCapacity();			    //扩充空间
	}
	if(i < 1 || i > this.length + 1){   //插入位置异常处理
		throw new RuntimeException("插入位置异常");
	}
	for(int index = length; index >= i; index--){//插入位置准备
		list[index] = list[index - 1];
	}
	list[i - 1] = element;              //在插入位置放入待插元素
	length++;                           //表长加1
}
  • 删除操作
    删除操作时将表的第i( 1 ≤ i ≤ 1\leq i\leq 1in)个元素删除,使长度为n的线性表(a1, … , ai-1, ai, … , an)变成长度为n-1的线性表(a1, … , ai-1, ai+1, …, an)。删除后元素ai-1和ai+1之间的逻辑关系发生了变化,且存储位置要反映这个变化。图3-1给出了顺序表在删除操作的前后,数据元素在存储空间中位置的变化。
    在这里插入图片描述
    注意元素移动方向,必须 从第i+1个元素(下标为i)开始移动,直至将最后一个元素前移为止,并且在移动元素之前要取出被删元素 。边界情况处理:1表空执行删除操作,则抛出下溢出异常;2元素删除位置不合理,则抛出位置错误异常。
public T delete(int i){
	if(isEmpty()){
		throw new RuntimeException("删除位置异常");
	}
	T element = list[i - 1];
	for(int j = i; j < length; j++){
		list[j - 1] = list[j];
	}
	length--;
	return element;
}

顺序表的使用

程序清单1-1 com/shaolong/sequentiallist/ListInterface.java

package com.shaolong.sequentiallist;
public interface ListInterface<T>{
	public void printList();             //遍历线性表
	public int length();                 //求线性表长度
	public int locate(T element);        //按值查找
	public T getElement(int i);          //按位查找
	public void insert(int i, T element);//在指定逻辑位置插入
	T delete(int i);                     //删除指定逻辑位置元素
	public boolean isEmpty();            //判断表空
}

程序清单1-2 com/shaolong/sequentiallist/SequentialList.java

package com.shaolong.sequentiallist;
public class SequentialList<T> implements ListInterface<T>{
	private T[] list;                        //顺序表存储
	private final static int LIST_SIZE = 100;//数组容量
	private int length;                      //线性表的长度
	//成员函数实现线性表的接口函数
	public SequentialList(){
		list = (T[])(new Object[LIST_SIZE]);
		length = 0;
	}
	public SequentialList(T[] init, int n){
		list = (T[])(new Object[LIST_SIZE]);//初始化泛型数组
		if(n > LIST_SIZE){//表长越界处理
			expandCapacity();
		}
		length = n;
		for(int i = 0; i < length; i++){
			list[i] = init[i];
		}
}
	private void expandCapacity(){
		T[] expandList = (T[])(new Object[list.length * 2]);//按两倍扩容
		for(int i = 0; i < list.length; i++){               //复制原有内容
			expandList[i] = list[i];
		}
		this.list = expandList;                             //扩容后引用复制
	}
	public boolean isEmpty(){
		if(length == 0){
			return true;
		}
		return false;
	}
	public int length(){
		return length;
	}
	public void printList(){
		if(isEmpty()) System.out.println("空表");
		for(int i = 0; i < length; i++){
			System.out.println(list[i] + " ");
		}
	}
	public int locate(T element){
		int result = 0;
		for(int i = 0; i < length; i++){
			if(list[i].equals(element)){
				result = i +1;
				break;
			}
		}
		return result;
	}
	public T getElement(int i){
		if(isEmpty()){
			throw new RuntimeException("表空");
		}
		if(i < 1 || i > length){
			throw new RuntimeException("查找位置非法");
		}
		T element = list[i - 1];
		return element;
	}
	public void insert(int i, T element){
		if(this.length == this.list.length){//表长越界处理
			expandCapacity();			    //扩充空间
		}
		if(i < 1 || i > this.length + 1){   //插入位置异常处理
			throw new RuntimeException("插入位置异常");
		}
		for(int index = length; index >= i; index--){//插入位置准备
			list[index] = list[index - 1];
		}
		list[i - 1] = element;              //在插入位置放入待插元素
		length++;                           //表长加1
	}
	public T delete(int i){
		if(isEmpty()){
			throw new RuntimeException("删除位置异常");
		}
		T element = list[i - 1];
		for(int j = i; j < length; j++){
			list[j - 1] = list[j];
		}
		length--;
		return element;
}
	
}

程序清单1-3 com/shaolong/sequentiallist/SequentialListTester.java

package com.shaolong.sequentiallist;
public class SequentialListTester{
	public static void main(String[] args){
		String[] initialList = {"a","b","c","d","e","f"};
		ListInterface<String> list = new SequentialList<String>(initialList, initialList.length);
		System.out.println("线性表的长度:" + list.length());
		System.out.println("当前线性表遍历结果:");
		list.printList();
		String list_2 = list.getElement(2);
		System.out.println("2号元素为:" + list_2);
		int locate_d = list.locate("d");
		System.out.println("数据元素d的逻辑位置为:" + locate_d);
		System.out.println("在位置3处插入k");
		list.insert(3, "k");
		String list_3 = list.getElement(3);
		System.out.println("3号元素为:" + list_3);
		System.out.println("线性表长度为:" + list.length());
		System.out.println("当前线性表的遍历结果为:");
		list.printList();
		System.out.println("删除位置3元素");
		String deleteElement = list.delete(3);
		System.out.println("删除的数据元素为:" + deleteElement);
		System.out.println("线性表的长度:" + list.length());
		System.out.println("当前线性表的遍历结果为:");
		list.printList();
	}
	
}

线性表的链接存储结构及实现

单链表的存储结构

  单链表(singly linked list)时用一组任意的存储单元存放线性表的元素,这组存储单元可以连续也可以不连续,甚至可以零散的分布在内存中的任意位置。现以单链表实现线性表的链接存储结构,单链表定义为实现ListInterface接口的Java类LinkedList,类中成员变量将实现单链表的存储结构,成员函数将实现线性表的接口函数。

public class LinkedList<T> implements ListInterface<T>{
	//成员变量实现单链表的存储结构
	//成员函数实现线性表的接口函数
}

  单链表存储结构为了能正确表示元素之间的逻辑关系,每个存储单元在存储数据的同时,还必须存储其后继元素所在的地址信息,如图4-1所示。
在这里插入图片描述
单链表中后继的地址信息称为链接,在java语言中用对象引用来表示链接。这两部分组成了数据元素的存储映像,称为结点(LinkedNode),结点结构如图5-1所示。
在这里插入图片描述
其中data为数据域,存放数据元素;next为后继引用域,存放结点后继引用。下面给出单链表的结点结构的定义:

public class LinkedNode<T>{
	private T data;//定义结点泛型数据域
	private LinkedNode<T> next;//定义节点后继引用域
	public LinkedNode(){
		data = null;
		next = null;
	}
	public LinkedNode(T element){//构造数据域为element值的结点
		data = element;
		next = null;
	}
	public T getData(){//获取data值
		return data;
	}
	public void setData(T element){//设置data域值
		data = element;
	}
	public LinkedNode<T> getNext(){//获取next值
		return next;
	}
	public void setNext(LinkedNode<T> successor){//设置next域值
		next = successor;
	}
}

单链表的实现

  在LinkedList类中,通过定义LinkedNode类型成员变量first(单链表头引用)实现单链表存储结构的定义。LinkedList类被实例化时,在内存中将依据成员变量定义开辟相应的存储结构。

public class LinkedList<T> implements ListInterface<T>{
	private LinkedNode<T> first; //头引用
	//成员函数实现线性表接口函数
}

  以单链表存储结构为基础,在LinkedList类中实现ListInterface接口中定义的抽象函数。

  • 空单链表的初始化
    通过无参构造函数实现类LinkedList的初始化,初始化仅一个不具有头结点的单链表,即将first置为null。
public LinkedList(){
	this.first = null;
}
  • 判空操作
    判断this.first是否为空,为空返回true,否则返回false。
public boolean isEmpty(){
	if(this.first == null){
		return true;
	}
	return false;
}
  • 遍历操作
    遍历单链表(printList)是指按照序号依次访问单链表中的所有结点。可以设置一个工作引用变量cur依次引用各个结点,当引用变量cur引用某结点时输出该节点的数据域。
public void printList(){
	LinkedNode<T> cur = this.first;//工作引用变量cur初始化
	while(cur != null){
		System.out.println(cur.getData() + " ");//输出当前结点数据域值
		cur = cur.getNext();//cur后移
	}
}
  • 求单链表的长度
    由于单链表类定义中没有存储线性表的 长度(length),因此不能直接获得线性表的 长度。可以采用遍历的 方法来求其长度。设置变量length,在遍历的过程中通过length累计单链表结点个数,最终返回length变量。算法实现如下:
public int length(){
	int length = 0;
	LinkedNode<T> cur = this.first;//初始化工作引用变量cur
	while(cur != null){
		length++;
		cur = cur.getNext();//cur后移
	}
	return length;
}
  • 按值查找
    在单链表中实现按值查找(locate)操作需要对单链表中的元素依次进行比较,如果查找成功,返回元素的序号,否则返回0表示查找失败。算法实现如下:
public int locate(T element){
	int pos = 1;
	LinkedNode<T> cur = this.first;
	while(cur != null){
		if(cur.getData().equals(element)){
			return pos;
		}
		cur = cur.getNext();
		pos++;
	}
	return 0;
}
  • 按位查找
    在单链表中,所有结点的引用都存储在前驱结点next中,因此即使知道被访问结点的逻辑序号i,也不能像顺序表那样直接按序号访问,只能从头引用除法顺着next域逐个结点往下搜索。需要设置工作引用cur,当工作引用cur引用结点i的时候,查找成功,返回i结点的数据域的值;否则,将工作引用变量向后移动 。对每个结点依次执行上述操作,知道cur为null时查找失败。算法如下:
public T getElement(int i){
	LinkedNode<T> cur = this.first;
	int count = 1;
	while(cur != null && count < i){
		cur = cur.getNext();
		count++;
	}
	if(cur == null){
		throw new RuntimeException("逻辑位置异常");
	}
	return cur.getData();
}
  • 插入操作
    单链表的插入操作(insert)是将值为参数element的新节点插入单链表的第i个位置,即插入ai-1与ai之间 。因此,必须先扫描单链表,找到ai-1的位置,然后生成一个新的数据域为element的新结点node。将结点node的next域存储结点ai的引用,将结点ai-1的next域存储新结点node的引用(注意引用的重置顺序),从而实现三个结点ai-1、node和ai之间逻辑关系的变化。
public void  insert(int i, T element){
	LinkedNode<T> pre = this.first;
	int count = 1;
	while( pre != null && count < i-1){
		pre = pre.getNext();
		count++;
	}
	if(pre == null){
		throw new RuntimeException("插入位置异常");
	}
	LinkedNode<T> node = new LinkedNode<T>(element);
	node.setNext(pre.getNext());
	pre.setNext(node);
}
  • 非空单链表的初始化
    通过有参构造函数实现非空单链表初始化,设给定的数据元素存放在数组init[n]中,建立存储这n个数据元素的单链表。有两种建立方法:头插法和尾插法。
    头插法建立单链表的算法如下:
public LinkedList(T[] init){
	for(int i = 0; i < init.length; i++){
		LinkedNode<T> node = new LinkedNode<T>(init[i]);
		node.setNext(node);
		this.first = node;
	}
}

尾插法建立单链表的算法如下:

public LinkedList(T[] init){
	LinkedNode<T> cur = this.first;
	for(int i = 0; i < init.length; i++){
		LinkedNode<T> node = new LinkedNode<T>(init[i]);
		if(i == 0){
			this.first = node;
			cur = node;
			continue;
		}
		cur.setNext(node);
		cur = cur.getNext();
	}
}
  • 删除操作(删除线性表中逻辑序号为i的结点)
    删除操作是将单链表的第i个结点删去。因为单链表中结点ai的引用变量存储在其前驱结点ai-1的next域中,所以必须先找到ai-1的位置,并让工作变量cur引用ai-1,然后将cur赋值为ai的后继结点,即把结点ai从链上摘下。需要注意表尾的特殊情况,此时虽然被删结点不存在,但其前驱结点却存在。因此仅当被删结点的前驱结点p存在且p不是终端结点时,才能确定被删结点存在。
public T delete(int i){
	LinkedNode<T> cur = this.first;
	int count = 1;
	while(cur != null && count < i-1){
		cur = cur.getNext();
		count++;
	}
	if(cur == null || cur.getNext() == null){
		throw new RuntimeException("删除位置异常");
	}
	T deleteNode = cur.getNext().getData();
	cur.setNext(cur.getNext().getNext());
	return deleteNode;	
}
  • 删除操作(删除线性表中data为key的第一个结点)
public void remove(T key){
	if(this.first == null) return;
	if(this.first.getData().equals(key)){
		this.first = this.first.getNext();
		return;
	}
	LinkedNode<T> pre = this.first;
	LinkedNode<T> cur = this.first.getNext();
	while(!cur.getData().equals(key) && cur != null){
		pre = cur;
		cur = cur.getNext();
	}
	if(cur != null){
		pre.setNext(cur.getNext());
	}
}
  • 删除操作(删除线性表中所有data为key的结点)
public void removeAll(T key){
	if(this.first == null) return;
	LinkedNode<T> pre = this.first;
	LinkedNode<T> cur = this.first.getNext();
	while(cur != null){
		if(cur.getData().equals(key)){
			pre.setNext(cur.getNext());
			cur = cur.getNext();
		}else{
			pre = cur;
			cur = cur.getNext();
		}
	}
	if(this.first.getData().equals(key)){
		this.first = this.first.getNext();
	}	
}

单链表的使用

程序清单2-1 com/shaolong/linkedlist/ListInterface.java

package com.shaolong.linkedlist;
public interface ListInterface<T>{
	public void printList();             //遍历线性表
	public int length();                 //求线性表长度
	public int locate(T element);        //按值查找
	public T getElement(int i);          //按位查找
	public void insert(int i, T element);//在指定逻辑位置插入
	T delete(int i);                     //删除指定逻辑位置元素
	public boolean isEmpty();            //判断表空
}

程序清单2-2 com/shaolong/linkedlist/LinkedNode.java

package com.shaolong.linkedlist;
public class LinkedNode<T>{
	private T data;//定义结点泛型数据域
	private LinkedNode<T> next;//定义节点后继引用域
	public LinkedNode(){
		data = null;
		next = null;
	}
	public LinkedNode(T element){//构造数据域为element值的结点
		data = element;
		next = null;
	}
	public T getData(){//获取data值
		return data;
	}
	public void setData(T element){//设置data域值
		data = element;
	}
	public LinkedNode<T> getNext(){//获取next值
		return next;
	}
	public void setNext(LinkedNode<T> successor){//设置next域值
		next = successor;
	}
}

程序清单2-3 com/shaolong/linkedlist/LinkedList.java

package com.shaolong.linkedlist;
public class LinkedList<T> implements ListInterface<T>{
	private LinkedNode<T> first; //头引用
	//成员函数实现线性表接口函数
	public LinkedList(){
		this.first = null;
	}
	public LinkedList(T[] init){
		LinkedNode<T> cur = this.first;
		for(int i = 0; i < init.length; i++){
			LinkedNode<T> node = new LinkedNode<T>(init[i]);
			if(i == 0){
				this.first = node;
				cur = node;
				continue;
			}
			cur.setNext(node);
			cur = cur.getNext();
		}	
	}
	public boolean isEmpty(){
		if(this.first == null){
			return true;
		}
		return false;
	}
	public void printList(){
		LinkedNode<T> cur = this.first;//工作引用变量cur初始化
		while(cur != null){
			System.out.println(cur.getData() + " ");//输出当前结点数据域值
			cur = cur.getNext();//cur后移
		}
	}
	public int length(){
		int length = 0;
		LinkedNode<T> cur = this.first;//初始化工作引用变量cur
		while(cur != null){
			length++;
			cur = cur.getNext();//cur后移
		}
		return length;
	}
	public int locate(T element){
		int pos = 1;
		LinkedNode<T> cur = this.first;
		while(cur != null){
		if(cur.getData().equals(element)){
				return pos;
			}
			cur = cur.getNext();
			pos++;
		}
		return 0;
	}
	public T getElement(int i){
		LinkedNode<T> cur = this.first;
		int count = 1;
		while(cur != null && count < i){
			cur = cur.getNext();
			count++;
		}
		if(cur == null){
			throw new RuntimeException("逻辑位置异常");
		}
		return cur.getData();
	}
	public void  insert(int i, T element){
		LinkedNode<T> pre = this.first;
		int count = 1;
		while( pre != null && count < i-1){
			pre = pre.getNext();
			count++;
		}
		if(pre == null){
			throw new RuntimeException("插入位置异常");
		}
		LinkedNode<T> node = new LinkedNode<T>(element);
		node.setNext(pre.getNext());
		pre.setNext(node);
	}
	public T delete(int i){
		LinkedNode<T> cur = this.first;
		int count = 1;
		while(cur != null && count < i-1){
			cur = cur.getNext();
			count++;
		}
		if(cur == null || cur.getNext() == null){
			throw new RuntimeException("删除位置异常");
		}
		T deleteNode = cur.getNext().getData();
		cur.setNext(cur.getNext().getNext());
		return deleteNode;	
	}
	public void remove(T key){
		if(this.first == null) return;
		if(this.first.getData().equals(key)){
			this.first = this.first.getNext();
			return;
		}
		LinkedNode<T> pre = this.first;
		LinkedNode<T> cur = this.first.getNext();
		while(!cur.getData().equals(key) && cur != null){
			pre = cur;
			cur = cur.getNext();
		}
		if(cur != null){
			pre.setNext(cur.getNext());
		}
	}
	public void removeAll(T key){
		if(this.first == null) return;
		LinkedNode<T> pre = this.first;
		LinkedNode<T> cur = this.first.getNext();
		while(cur != null){
			if(cur.getData().equals(key)){
				pre.setNext(cur.getNext());
				cur = cur.getNext();
			}else{
				pre = cur;
				cur = cur.getNext();
			}
		}
		if(this.first.getData().equals(key)){
			this.first = this.first.getNext();
		}	
	}
	
}

程序清单2-4 com/shaolong/linkedlist/LinkedListTester.java

package com.shaolong.linkedlist;
public class LinkedListTester{
	public static void main(String[] args){
		String[] initialList = {"a","b","c","d","e","f"};
		ListInterface<String> list = new LinkedList<String>(initialList);
		System.out.println("线性表的长度:" + list.length());
		System.out.println("当前线性表遍历结果:");
		list.printList();
		String list_2 = list.getElement(2);
		System.out.println("2号元素为:" + list_2);
		int locate_d = list.locate("d");
		System.out.println("数据元素d的逻辑位置为:" + locate_d);
		System.out.println("在位置3处插入k");
		list.insert(3, "k");
		String list_3 = list.getElement(3);
		System.out.println("3号元素为:" + list_3);
		System.out.println("线性表长度为:" + list.length());
		System.out.println("当前线性表的遍历结果为:");
		list.printList();
		System.out.println("删除位置3元素");
		String deleteElement = list.delete(3);
		System.out.println("删除的数据元素为:" + deleteElement);
		System.out.println("线性表的长度:" + list.length());
		System.out.println("当前线性表的遍历结果为:");
		list.printList();
		initialList = new String[]{"a","a","a","a","a","a"};
		list = new LinkedList<String>(initialList);	
		System.out.println("线性表的长度:" + list.length());
		System.out.println("当前线性表遍历结果:");
		list.printList();
		System.out.println("======删除第一个data域为key的元素=======");
		((LinkedList<String>)list).remove("a");
		System.out.println("线性表的长度:" + list.length());
		list.printList();
		System.out.println("======删除所有data域为key的元素=========");
		((LinkedList<String>)list).removeAll("a");
		System.out.println("线性表的长度:" + list.length());
		list.printList();
	
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值