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

数据结构与算法学习笔记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)。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章