集合----链式存储的实现

来源:互联网 发布:九年级下册历史书淘宝 编辑:程序博客网 时间:2024/04/24 03:45

一 、链表的概念

集合的顺序存储是通过数组来实现的,集合的链式存储是通过存储结点之间的链接来实现的,从而形成链表。链表中的每一个结点都包含一个值域和一个指针(即引用对象域),每个结点的指针指向下一个结点对象,这样的链表称之为单链表。在单链表中,第一个结点称之为表头结点,指向第一个结点的指针被称为表头指针,最后一个结点称为表尾结点,表尾结点的指针为空。通常,为了方便插入和删除结点,通常在表头结点增加一个无值的结点,我们称之为附加头结点,用head表示,如链表为空,附加头结点的指针域指向自身,指针域为空,若链表不为空,则附加头结点的指针指向第一个结点。如下图所示。


这里写图片描述


二 、结点类的定义

我们定义类名为Node,数值域和指针域分别用element和next表示。该类包括两个构造方法,一个只带有结点引用对象参数,实现对当前next结点的赋值;另一个带有两个参数,分别实现对当前结点的值域element和指针域next的赋值。Node结点的定义如下:

public class Node {    Object element;    Node next;    public Node(Node next){        this.next = next;    }    public Node(Object element,Node next){        this.element = element;        this.next = next;    }}

三 、具体操作的实现

1 、初始化集合,首先我们要定义附加头结点head为null和链表的长度length为0,然后再定义一个无参构造方法。

public class LinkedSet {    public Node head;    public int length;    public LinkedSet(){        head = new Node(null);        length = 0;    }}

2 、向集合中添加一个元素

    public boolean add(Object obj){        Node temp = head;       //定义一个Node类型的临时变量,指向附加头结点        while(temp.next!=null){     //是否为链表最后的结点            if(temp.next.element.equals(obj)){  //判断链表中是否有与obj内容相同的结点                return false;            }else{                temp = temp.next;   //如果不是,则取下一个结点            }        }        temp.next = new Node(obj,null); //temp为链表的最后一个结点,并在该结点后创建一个新的结点        length++;           //链表的长度加1        return true;    }

3 、从集合中删除一个元素

    public boolean remove(Object obj){        Node temp = head;       //定义一个Node类型的临时变量,指向附加头结点        while(temp.next!=null){     //循环遍历单链表            if(temp.next.element.equals(obj)){      //判断是否存在相同的元素,若存在,则跳出循环                break;            }            temp = temp.next;           //修改temp,指向后继结点        }        if(temp.next!=null){        //条件成立时,temp.next指要删除的结点            temp.next = temp.next.next;     //从链表中删除该结点            length--;                       //链表长度减1            return true;                    //删除成功返回true        }        return false;                       //删除失败返回false    }

4 、判断一个元素是否属于该集合

    public boolean contains(Object obj){        Node temp = head.next;      //定义一个Node类型的临时变量,指向第一个结点        while(temp!=null){      //循环遍历单链表            if(temp.element.equals(obj)){   //判断是否存在相同的元素,若存在,则返回true                return true;            }            temp = temp.next;       //修改temp,指向后继结点        }        return false;               //若不存在,则返回false    }

5 、返回集合中第i个元素的值

    public Object get(int index){        if(index<1||index>length){            System.out.println("该索引不在集合范围内");            System.exit(1);     //结束该方法        }        Node temp = head;       //定义一个Node类型的临时变量,指向附加头结点        int i = 1;                      while(i<=index){        //定义一个变量,用来表示循环的次数            temp = temp.next;   //修改temp,指向后继结点            i++;                //i自动加1        }        return temp.element;    //返回查找结点的内容    }

6 、从集合中按值查找元素

    public Object find(Object obj){        Node temp = head.next;      //定义一个Node类型的临时变量,指向第一个结点        while(temp!=null){          //循环遍历单链表            if(temp.element.equals(obj)){       //判断是否存在相同的元素,若存在,则返回obj                return obj;            }            temp = temp.next;           //修改temp,指向后继结点        }        return null;                    //查找失败返回null    }

7 、返回集合的长度

public int size(){        return length;    }

8 、判断集合是否为空

public boolean isEmpty(){        return length==0;    }

9 、输出集合的所有元素

public void print(){        Node temp = head.next;        while(temp!=null){            System.out.print(temp.element.toString()+" ");        }        System.out.println();    }

10 、求两个集合的并集

public LinkedSet union(LinkedSet set){        LinkedSet setTemp = new LinkedSet();    //定义一个新的链表,用来存放两个集合的并集        //setTemp添加当前集合的元素        Node temp = head.next;        while(temp!=null){            setTemp.add(temp.element);            temp = temp.next;        }        //setTemp添加set集合的元素        Node h = set.head.next;        while(h!=null){            setTemp.add(h.element);            h = h.next;        }        return setTemp;    }

11 、求两个集合的交集

public LinkedSet intersection(LinkedSet set){        LinkedSet setTemp = new LinkedSet();        //setTemp添加当前集合的元素        Node temp = head.next;        while(temp!=null){      //遍历当前对象的所有结点            if(set.contains(temp.element)){     //判断set集合是否包含该元素                setTemp.add(temp.element);      //如果包含该元素,则添加到setTemp中            }            temp = temp.next;               //temp指向后继结点        }           return setTemp;    }

12 、清除集合中的所有元素

    public void clear(){        length = 0;             //将链表的长度设置为0        head.next = null;       //将附加头结点的next置为null,如果不置为null,则该链表的元素还存在    }

总结

单向链表的具体操作还是比较简单的,通过与集合的顺序表相比,我们很明显的发现,链表的插入和删除比顺序表要方便的多,顺序表需要对数组元素进行移动,而链表只需要改变指针域即可。但是对于查找操作来说顺序表效率更高,通过索引即可查找,而链表则需要进行遍历,大大的降低了效率。

0 0
原创粉丝点击