数据结构与算法学习笔记02_2(线性表)

来源:互联网 发布:5g数据的市场需求 编辑:程序博客网 时间:2024/05/16 19:05

数据结构与算法学习笔记02_2(线性表)

 

2、线性表的链式存储结构

 

单链表

除了存储其本身的信息外,还需存储一个指示其直接后继的存储位置的信息。

我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。链表中的第一个结点的存储位置叫做头指针,最后一个结点指针为(NULL)

 

头指针与头结点的异同

1、头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。

2、头指针是链表的必要元素

3、头结点是为了操作的统一和方便而设立的,放在第一个元素的结点之前,其数据域一般无意义(但也可以用来存放链表的长度)。

4、头结点不一定是链表的必须要素

 


实现:

typedefstructNode

{

       ElemType  data;     //数据域

       struct  Node*Next// 指针域

} Node;

typedef  struct Node*LinkList;

 

单链表的读取:

获得链表第i个数据的算法思路:

声明一个结点p指向链表第一个结点,初始化j从1开始;

当j<i时,就遍历链表,让p的指针向后移动,不断指向一下结点,j+1;

若到链表末尾p为空,则说明第i个元素不存在;

否则查找成功,返回结点p的数据。

实现:

status GetElem(LinkList L, int i, ElemType* e){int j;LinkList p;p = L->next;j = 1;while (p&&j<i){p = p->next;++j;}if (!p||j>i){return ERROR;}*e = p->data;return Ok;}

由于单链表的结构中没有定义表长,所以不能实现知道要循环多少次,因此也就不方便使用for来控制循环。

 

单链表的插入


我们思考后发觉根本用不着惊动其他结点,只需要让s->next和p->next的指针做一点改变。

s->next= p->next;

p->next= s;

这两句是无论如何不能弄反的。

 

单链表第i个数据插入结点的算法思路:

声明一结点p指向链表头结点,初始化j从1开始;

当j<1时,就遍历链表,让p的指针向后移动,不断指向下一结点,j累加1;

若到链表末尾p为空,则说明第i个元素不存在;

否则查找成功,在系统中生成一个空结点s;

将数据元素e赋值给s->data;

单链表的插入刚才两个标准语句;

返回成功。

实现:

Status ListInsert(LinkList* L, int i, ElemType e){int j;LinkList p, s;p = *L;j = 1;while (p&&j<i){p = p->next;j++}if (!p||j>i){return ERROR;}s = (Listlist)malloc(sizeof(Node));s->data = e;s->next = p->next;p->next = s;return Ok;}

单链表的删除


单链表第i个数据删除结点的算法思路:

声明结点p指向链表第一个结点,初始化j=1;

当j<1时,就遍历链表,让P的指针向后移动,不断指向下一个结点,j累加1;

若到链表末尾p为空,则说明第i个元素不存在;

否则查找成功,将欲删除结点p->next赋值给q;

单链表的删除标准语句p->next = q->next;

将q结点中的数据赋值给e,作为返回;

释放q结点。

实现:

Status ListDelete(LinkList *L, int i, ElemType *e){int j;LinkList p, q;p = *L;j = 1;while (p->next&&j<i){p = p->next;++j;}if (!(p->next)||j>i){return ERROR;}q = p->next;p->next = q->next;*e = q->data;free(q);return Ok;}

效率分析:

无论是单链表插入还是删除算法,它们其实都是由两个部分组成:第一部分就是遍历查找第i个元素,第二部分就是实现插入和删除元素。从整个算法来说,我们很容易可以推出它们的时间复杂度都是O(n)。

 

再详细点分析:

如果在我们不知道第i个元素的指针位置,单链表数据结构在插入和删除操作上,与线性表的顺序存储结构是没有太大优势的。

但如果,我们希望从第i个位置开始,插入连续10个元素,对于顺序存储结构意味着,每一次插入都需要移动n-i个位置,所以每次都是O(n)。

 

而单链表,我们只需要在第一次时,找到第i个位置的指针,此时为O(n),接下来只是简单地通过赋值移动指针而已,时间复杂度都是O(1)。

显然,对于插入或删除数据越频繁的操作,单链表的效率优势就越是明显啦~

0 0