数组中取值可以根据下标获取指定的值,但链表不行,链表中逻辑相邻的元素,在物理上不一定是相邻的。链表中取值只能从首元结点开始,通过指针域依次访问。
单链表取值的算法分析如下
(1) 按所取元素的位置,从首元结点开始,遍历整个链表。
(2) 设置计数器,遍历链表时,计数器自增,当计数器值与所取值的序号相同时,结束循环
(3) 输出所取的值。
算法的思想大致如上述描述,函数的实现考虑返回值和形参。
(1) 返回值,对于取数而言,存在已获取值和未获取值,所以可以定义如下:
#define OK 1
#define ERROR 0
#define VOERFLOW -2
typedef int Status;
函数类型为int类型,成功取值返回1,未获取值返回0。
(2) 函数形参,需要对链表进行取值,所以首先要传入链表,然后需要考虑具体取哪个序号的值,最后将所取的值存在哪?按上述考虑,可以将函数声明如下
Status GetElem(LinkList L, int i, int &e)
其中LinkList L是需要取值的链表,i是取值的序号,&e采用引用的方式,将值进行存储。
具体实现算法时,参考下图
(1) 定义指针变量p,指向首元结点,因为链表取值,遍历链表时只需要从首元结点开始遍历。
LinkList p;
p = L->next;
p是指针变量,结构体指针类型,首元结点的地址由头指针L获取,即L->next
(2) 将指针p移动到所取值的结点。这时候需要使用循环,链表结点数量不确定,所以循环次数不确定,使用while循环。函数传参时,传输需要取值的需要,所以在循环过程中设置计数器j,只要i和j的值相等时,结束循环,但其中需要再考虑结点不为空。
while((p != NULL) && (j<i)){
p = p->next;
j ;
}
只要p不为空,且j<i时就会一直循环,当j=i时结束循环。
(3) 如果结点p为空,或者计数器的值大于传入的序号i值,那返回error
(4) 循环结束,此时计数器的值等于传入的序号i值,所以此时指针p指向了所取数值的结点,只要获取此结点的数据域即可。
e = p->data;
完整的代码参考如下
Status GetElem(LinkList L, int i, int &e){
int j = 1;
LinkList p;
p = L->next;
while((p != NULL) && (j<i)){
p = p->next;
j ;
}
if(!p || j>i) return ERROR;
e = p->data;
return OK;
}