1.线性表的头指针与尾指针
对于线性表来说,总得有个头有个尾,链表也不例外。我们把链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行了。之后的每一个结点,其实就是上一个的后继指针指向的位置。想象一下, 最后-一个结点,它的指针指向哪里?
最后一个,当然就意味着直接后继不存在了,所以我们规定,线性链表的最后一个结点指针为“空”(通常用NULL或“^”符号表示)。
2.头节点
有时,为了更方便地对链表进行操作,会在单链表的第一个结点前附设一个节点,称为头节点
头节点的数据域可以不存储任何信息,也可以存储如线性表的长度等附加信息,头结点的指针域存储指向第一个结点的指针。
3.头节点与头指针的异同点:
头指针:
1.头指针是指向链表指向第一个结点的指针,如果链表有头节点,则是指向头节点的指针
2.头指针具有标识作用,所以常用头指针冠以链表的名字
3.无论链表是否为空,头指针均不为空。头指针是链表的必要元素,只要链表存在即使是空链表,头指针也会存在
头结点:
1.头结点时为了操作的统一和方便而设立的,放在第一元素的结点之前,其数据域一般无意义(也可存放链表的长度)
2.有了头结点,对在第一元素结点前插入结点和删除第一结点,其操作与其他结点的操作就同意了
3.头结点不一定是链表必须要素
4.空链表
空链表就算头结点的指针域为空,即NULL
带有头结点的空链表
带有头结点的单链表
代码如下
//头文件
#include<stdio.h>
//宏定义
#define OK 1
#define ERROR 0
//写链式线性表的GetElem方法
//参数:链式线性表L,i,返回的*e
//操作目的:获取第i个元素的值并返回。
int GetElem(Node L,i,int *e){
//操作过程:1.定义一个结点P,使这个结点P指向头结点,在j<i的条件下,逐次向后移动
结点P的指向,直到找到第i个数,并返回
LinkList P;
int j;
P=L;
for(j=0;j<i;j++){
P=P->Next;
if(P==NULL){//如果P为空则说明第i个元素不存在,返回异常
return ERROR;
}
}
if(j>i || !p){//如果i为0,或者负数,或者p为空
return ERROR;
}
*e=P->data;
return OK;
}
采用事前分析估算方法,对时间复杂度进行分析:
最好的情况是:如果是i等于1的情况的,那么时间复杂度为O(1);
最坏的情况是:如果i是链表的最后一个,那么for需要遍历n次,当然了,如果一开始指针P指向第一个结点即头结点后面的结点,那么遍历n-1次,那么时间复杂度为O(n);
所以平均执行次数为T(n+1/2)
那么平均时间复杂度为O(n);