线性表之单链表

来源:互联网 发布:淘宝双十一销量排行 编辑:程序博客网 时间:2024/04/30 15:12

顺序表在进行插入和删除操作需要移动大量元素,而且当线性表长度变化较大时,难以确定存储空间的容量,造成存储空间的碎片。

一、单链表的存储结构

所有的元素都不用考虑相邻位置,哪里有空位就到哪里,只要让每个元素存储后继元素的内存地址,这样就可以在第一个元素知道第二个元素的位置。我们把存储数据的域叫做数据域,存储位置的域叫做指针域,指针域中存储的信息叫做指针或链,这两部分信息组成了一个结点。每个结点只包含一个指针域,所以叫做单链表。链表中第一个结点的存储位置叫做头指针。数据域即是数据元素。

数据元素可以存在内存未被占用的任意位置。
这里写图片描述

这里写图片描述

一般为了方便对链表进行操作,会在单链表的第一个结点前附设一个结点,成为头结点。头结点的数据域可以不保存任何信息。有了头结点,对在第一个元素结点前插入结点和删除第一结点,其操作与其他结点的操作就统一了;

这里写图片描述

二、单链表的存储示意图

这里写图片描述

假设P是指向线性表的第i个元素的指针,则该节点ai的数据域我们可以用p->data来表示,p->data的值是一个数据元素,结点ai的指针域可以用p->next来表示,p->next的值是一个指针。如果p->data=ai,那么p->next->data=ai+1。即:

这里写图片描述

指针p可以理解为一个引用,指向ai,p->data就是ai->data。

单链表结构与顺序存储结构优缺点:
这里写图片描述

三、单链表的java实现

public class Node {    public Object data;// 数据域    public Node next;// 指针域    public Node() {        this(null);    }    public Node(Object data) {        this.data = data;        this.next = null;    }    public void show() {        System.out.println("data=" + data);    }}
public class SingleList {    private Node head;// 头结点    private int size;// 链表的大小    public SingleList() {        // 没有数据的头结点        head = new Node();        size = 0;    }    public SingleList(Object[] datas) {        int n = datas.length;        head = new Node();        Node p = head;        for (int i = 0; i < n; i++) {            p.next = new Node(datas[i]);            p = p.next;        }        size = n;    }    public void add(Object o) {        Node p;        if (size == 0)            p = head;        else {            p = getp(size + 1);        }        p.next = new Node(o);        size++;    }    // 得到插入结点的前一个结点    public Node getp(int i) {        Node p = head;        if (i > 0 && i <= size + 1) {            for (int j = 1; j < i; j++) {                p = p.next;            }        }        return p;    }    // 向第i个位置插入结点    public void insert(int i, Object o) {        if (i > size)            System.out.println("超出链表大小");        Node p = getp(i);        Node p2 = new Node(o);        p2.next = p.next;        p.next = p2;        size++;    }    public Object get(int i) {        Node p = getp(i);        return p.next.data;    }    public void remove(int i) {        if (i > 0 && i <= size) {            Node p = getp(i);            p.next = p.next.next;            size--;        }    }    public void set(int i, Object o) {        Node p = getp(i);        p.next.data = o;    }    public int indexof(Object o) {        Node p = head.next;        int i = 1;        while (!p.data.equals(o)) {            p = p.next;            i++;        }        if (i <= size)            return i;        else            return -1;    }    public void showall() {        Node p = head.next;        while (p != null) {            p.show();            p = p.next;        }    }    public boolean isEmpty() {        if (size == 0)            return true;        else            return false;    }    // 清空单链表,保留头结点    public void clear() {        Node p = head.next;        Node q;        while (p != null) {            q = p.next;            p = null;            System.gc();            p = q;        }        size=0;    }    public int size() {        return size;    }}
0 0