1、单链表的读取
算法思路:
(1) 声明一个结点 p 指向链表第一个结点(这里是存储数据的第一个节点,不是头结点),初始化 j 从 1 开始;
(2) 当 j < i 时,就遍历链表,让 p 的指针向后移动,不断指向下一结点, j 累加 1;
(3) 若到链表末尾 p 为空,则说明第 i 个元素不存在;
(4) 否则查找成功,返回结点 p 的数据 。
代码:
Status GetElem(LinkList *L, int i, ElemType *e)
{
LinkList p;
p = (*L)->next;
int j = 1;
while (p&&j < i)
{
p = p->next;
j++;
}
if (!p || j>i)/*貌似出现不了j>i的情况。。。;超出范围时,p=NUll*/
return ERROR;
*e = p->data;
return OK;
}
注:由于单链表的结构中没有定义表长,所以不能事先知道要循环多少次,因此也就不方便使用 for 来控制循环。其主要核心思想就是 “工作指针后移’ ,这其实也是很多算法的常用技术。
2、单链表的插入
算法思路:
(1) 声明一结点 p 指向链表第一个结点(这里是头结点),初始化 j 从 1 开始;
(2) 当 j < i 时,就遍历链表,让 p 的指针向后移动,不断指向下一结点, j 累加 1;
(3) 若到链表末尾 p 为空,则说明第 i 个元素不存在;
(4) 否则查找成功,在系统中生成一个空结点 s;
(5) 将数据元素 e 赋值给 s->data ;
(6) 单链表的插入标准语旬 s->next=p->next; p->next=s ;
(7) 返回成功 。
逻辑图:
代码:
Status ListInsert(LinkList *L, int i, ElemType e)
{
int j=1;
LinkList p,s;
p = (*L);/*头结点*/
while (p&&j < i)
{
p = p->next;
j++;
}
if (!p->next||j>i)
return ERROR;
s = (LinkList)malloc(sizeof(Node));/*因为s是插入的新节点,所以要为它分配内存空间,区别于
其他函数的临时节点,临时节点不需要分配空间*/
s->data=e;
s->next = p->next;
p->next = s;
return OK;
}
3、单链表的删除
算法思路:
- 声明一结点 p 指 向链表第一个结点 , 初始化 j 从 1 开始;
- 当j < i时,就遍历链表, 让 p 的指针向后移动,不断指向下一个结点,j累加1;
- 若到链表末尾 p 为空,则说明第 i 个元素不存在;
4 . 否则查找成功,将欲删除的结点 p-> next 赋值给 q ;
5 . 单链表的删除标准语句 p->next=q->next;
6 . 将 q 结点中的数据赋值给 e, 作为返回;
7 . 释放 q 结点;
8 . 返回成功。
逻辑图:
代码:
Status ListDelete(LinkList *L, int i, ElemType *e)
{
LinkList p,s;
p = (*L);/*头结点*/
int j=1;
/*因为p为要删除节点的前一节点,所以需要用p->next判断是否超出链表范围*/
while (p->next&&j < i)
{
p = p->next;
j++;
}
if (!(p->next) || j>i)
return ERROR;
//s = (LinkList)malloc(sizeof(Node));/*临时节点,不需要分配内存*/
s = p->next;
*e = s->data;
p->next = s->next;
free(s);
return OK;
}
4、单链表结构与顺序存储结构优缺点