《数据结构》个人笔记4
一.单链表的定义和表示
1.线性表链式存储结构的特点:
- 用一组任意的存储单元(可连续也可以不连续)存储线性表的数据元素。
2.单链表:
- 单链表的存取必须从头指针开始进行,头指针指示链表中第一个节点。
- 由于最后一个数据元素没有直接后继,则单链表中最后一个结点的指针为空(NULL)。
- 用单链表表示线性表时,数据元素之间的逻辑关系是由结点中的指针指示的。
单链表可由头指针唯一确认,在C语言中可用“结构指针”来描述(单链表的初始化):
typedef struct LNode
{
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode,*LinkList;//LinkList为指向结构体LNode的指针类型
- LinkList与LNode*两者本质上是等价的。通常习惯用LinkList来定义单链表,强调定义的是某个单链表的头指针。
- 注意区分指针变量和结点变量两个不同概念, ,若定义LinkList p或LNode *p,则p为指向某结点的指针变量,表示该结点的地址;而 *p为对应的结点变量,表示该结点的名称。
- *p指的是指针指向的内存地址中存放的内容。
- p是一个指针变量的名字,表示指针变量指向的内存地址。
- L指的是头节点指针。
二.单链表基本操作的实现:
1.单链表的初始化
- 思路:
1.生成新结点作为头节点,用头指针L指向头结点。
2.头结点的指针域置空。
算法描述:
typedef struct LNode
{
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode,*LinkList;//LinkList为指向结构体LNode的指针类型
2.单链表的取值
一.和顺序表的不同
链表中逻辑相邻的结点并没有存储在物理相邻的单元中,这样,根据给定的结点位置序号i,在链表中获取该结点的值不能像顺序表那样随机访问,而只能只能从链表的首元结点出发,顺着链域next逐个结点向下访问。
二.思路:
1.用指针p指向首元结点,用j做计数器初值赋为1.
2.从首元结点开始依次顺着链域next向下访问,只要指向当前结点的指针p不为空(NULL),并且没有达到序号为i的结点,则循环执行以下操作:
- p指向下一个结点;
- 计数器j相应加1。
3.退出循环时,如果指针p为空,或者计数器j大于i,说明指定的序号i值不合法(i大于表长n或i小于等于0),取值失败返回ERROR;否则取值成功,此时j=i时,p所指的结点就是要找的第i个结点,用参数e保存当前结点的数据域,返回OK。
算法描述:
Status GetElem(LinkList(LinkList L,int i,ElemType &e)
{
p=L->next;
j=1;
while(p&&j<i)
{
p=p->next;
++j;
}
if(!p||j>i) return ERROR;
e=p->data;
return OK;
}
3.单链表的查找
一.思路:
1.用指针p指向首元结点。
2.从首元结点开始开始依次顺着链域next向下查找,只要指向当前结点的指针p不为空,并且p所指结点的数据域不等于给定的值e,则循环执行以下操作:p指向下下一个结点。
3.返回p。若查找成功,p此时即为结点的地址值,若查找失败,p的值即为NULL。
LNode *LocateElem(LinkList L,ElemType e)
{
p=L->next;
while(p&&p->data!=e)
p=p->next;
rerurn p;
}
4.单链表的插入
单链表的插入不需要像顺序表的插入操作那样需要移动元素。
一.思路
将值为e的新结点插入到表的第i个结点的位置上,即插入到结点a(i-1)与ai之间:
- 查找结点a(i-1)并由指针p指向该结点。
- 生成一个新结点*s。
- 将新结点*s的数据域置为e。
- 将新结点*s的指针域指向结点ai。
- 将结点p的指针域指向新结点s。
Status ListInsert(LinkList &L,int i,ElemType e)
{
p=L;j=0;
while(p&&(j<i-1))
{p=p->next;++j; }
if(!p||j>i-1) return ERROR;
s=new LNode;
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
5.单链表的删除
一.思路:
1.查找结点a(i-1)并由指针p指向该结点。
2.临时保存待删除结点a(i)的地址q中,以备释放。
3.将结点*p的指针域指向a(i)后直接释放。
4.释放结点a(i)的空间。
Status ListDelete(LinkList &L,int i)
{
p=L;j=0;
while((p->next)&&(j<i-1))
{
p=p->next;++j;
}
if(!(p->next)||(j>i-1)) return ERROR;
q=p->next;
p->next=q->next;
delete q;
return OK;
}