单链表是最简单的链表结构,但也是最基本的链表结构。
一个链表由若干个链表结点连接而成。在单链表中,每个链表结点包括两个域:用来存储数据的数据域和用来连接下一个链表结点的指针域。为了访问到链表中的结点,每个
1、基本概念
链表有一个相关联的指针,该指针指向链表中的第一个结点,这个指针称为头指针。
通过指针head可以访问到表头结点,通过前一个结点的指针可以访问到后一个结点,当前结点指针为空时,说明已经到达表尾结点。
和顺序存储相比,无论是从链表中删除一个元素还是往链表中插入一个元素都要方便的多,不涉及任何结点的移动,只需要修改结点的链指针。
不含结点的链表称为空链表,此时,head为空(NULL)。通过判断head是否等于NULL,可以确定一个链表是否为空链表。当在链表中插入一个结点时,首先要判断链表是否为空链表,如果是空链表,则修改head使之直接指向要插入的结点即可;否则,由head指向的表头开始寻找到插入位置,找到后,将要插入的结点插入到链表中。
为了插入方便,实际应用中可以采用附加头结点的方式来组织链表,此时,头指针所指向的结点不是表头,而是一个特殊的结点,这个结点不用来存储任何数据。因此,当链表为空链表时,头指针不是空指针,于是,在对链表进行操作时,无须判断头指针是否为空。这个附加的结点称为附加头结点,附加头指针指向的结点才是表头结点。请注意附加头结点与表头结点两者之间的差别。
2、单链表结点类
单链表结点类除封装数据和指针这两个基本要素外,还包括一个对结点进行初始化处理的方法、一个获取指向后继结点指针的方法、一个在结点后插入元素的方法以及一个删除当前结点的后继结点的方法。对于每个结点,主要的操作都是与它的后继结点直接相关。
3、单链表类
利用单链表结点类可以构建单链表类。显然,单链表类中必须包含基本的数据成员表头指针front和表尾指针rear。此外,为了处理方便,单链表类中还应包含如下数据成员:单链表长度(结点个数)size、当前结点位置position、当前结点指针currPtr、指向当前结点前驱的指针prevPtr。单链表是动态存储的数据结构,因此,单链表类中应该包含申请和释放单链表结点所需空间的方法、以及有关插入、删除、访问、修改、移动当前结点指针、获取单链表信息等方法。
4、栈的单链表实现
栈作为一种主要的动态数据结构,可以在单链表类LinkedList的基础上加以实现。实现的方式有两种:一种是在栈类LinkedStack中定义一个LinkedList对象作为存储栈数据的私有成员;另一种是以LinkedList类为基类,通过类的继承而实现LinkedStack类。采用第一种实现方式可以方便的建立栈数据结构。此时,栈类中包括一个单链表对象私有成员,此外,还包括对栈进行操作以及查询栈状态的公有成员函数。
5、链式队列
基于LinkedList类,也可以非常方便地实现队列。和基于链表类实现栈类一样,链式队列类也可以有不同的实现方法。因为LinkedList类中的插入、删除运算是局部操作,涉及在队列中调用重定位操作Setposition,因此,不能保证这样的链式队列的插入、删除运算时间为O(1)。为了方便实现链式队列,在下面的基于node类的链式队列类LinkedQueue中,只需定义几个基本的队列操作方法即可,这些方法主要包括在队列中插入元素(入队列)的方法、从队列中删除元素(出队列)的方法、读取队列头结点的数据的方法以及查询队列状态的方法。