数据结构与算法基础(二)之线性表的链式存储与指针的概念
2016-02-26 17:06
302 查看
上一节我们讨论到了线性表的顺序存储结构的缺点,那就是在进行插入和删除操作的时候需要移动大量的元素,为了解决这个问题,我们可以想到的方法有很多,比如说在相邻元素之间留出一定的位置给待插入的元素使用,但是这样非常浪费空间,而且插入删除操作的具体位置和元素的数量是未知的,这样并不是最好的解决方法。
这个时候就需要我们在C语言学习时接触到的“指针”上场了。
首先,什么是指针呢?指针就编程语言中的一个对象或变量,用来存储某一个地址,这个地址的值直接指向(points to)存在电脑存储器中另一块存储空间的值。作个比喻,假设将电脑存储器当成一本书,一张内容记录了某个页码加上行号的便利贴,可以被当成是一个指向特定页面的指针;根据便利粘贴面的页码与行号,翻到那个页面,把那个页面的那一行文字读出来,就相当于是对这个指针进行反参考的动作。(来自维基百科词条指针)
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以存在内存中未被占用的位置。这一点和顺序存储结构不同,也就是说线性表的元素不一定要按照顺序来,只需要放在任意内存未被占用的位置即可。顺序存储结构每个数据元素只需要存储一个位置就可以,而链式存储结构中除了要存储数据元素信息外还要存储它的后继元素的存储地址(指针)。
我们把存储数据元素信息的域称之为数据域,把存储后直接后继位置的域称为指针域。指针域中存储的信息称为指针或链。这两部分信息组成结点(Node)。
n个结点链接成一个链表,即为线性表(a1,a2,a3.....,an)的链式存储结构。我们把链表中第一个结点称为头指针,最后一个节点指针为空(NULL)。如下图所示:
关于线性表的顺序存储和链式存储的区别,我想到一个例子来进行比喻。比如说我们去银行柜台办理银行卡和体育课站队列这两种情景。前者,在柜台办理业务时要去抽取一个号码,拿到号码之后只需要随意找个位子等着自己被叫号即可,那么不管顾客站在哪里等待,依然是按照顾客抽号的顺序来办理业务的,叫到自己的号码时便可以上前办理业务。后者,体育课上要按照身高排队列,排好之后如果有同学迟到晚来了,那么就根据他的身高来确定他要插入的位置,相应地,这位同学所处位置之后的同学就要往后移动一个位置。
假设p是指向线性表第i个元素的指针,则该结点ai的数据域我们可以用p->data的值是一个数据元素,结点ai的指针域可以用p->next来表示,p->next的值是一个指针。举个例子,如果p->data=ai,那么p->next->data=ai+1。
单链表读取元素的核心思想就是:工作指针后移。算法的时间复杂度依然取决于元素位置,如果在第一个位置那么时间复杂度为O(1),否则就要指针一个个后移直到找到那个元素。
易混淆的两个概念:头指针和头结点
头结点是指在单链表的第一个结点之前附设的一个结点。头结点的数据域可以为空也可以存储如线性表长度等的附加信息。头结点的指针域指向第一个结点的指针也就是第一个元素结点的存储位置。
单链表中可以没有头结点但是不能没有头指针,如果没有头结点则直接指向第一个结点。
这个时候就需要我们在C语言学习时接触到的“指针”上场了。
首先,什么是指针呢?指针就编程语言中的一个对象或变量,用来存储某一个地址,这个地址的值直接指向(points to)存在电脑存储器中另一块存储空间的值。作个比喻,假设将电脑存储器当成一本书,一张内容记录了某个页码加上行号的便利贴,可以被当成是一个指向特定页面的指针;根据便利粘贴面的页码与行号,翻到那个页面,把那个页面的那一行文字读出来,就相当于是对这个指针进行反参考的动作。(来自维基百科词条指针)
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以存在内存中未被占用的位置。这一点和顺序存储结构不同,也就是说线性表的元素不一定要按照顺序来,只需要放在任意内存未被占用的位置即可。顺序存储结构每个数据元素只需要存储一个位置就可以,而链式存储结构中除了要存储数据元素信息外还要存储它的后继元素的存储地址(指针)。
我们把存储数据元素信息的域称之为数据域,把存储后直接后继位置的域称为指针域。指针域中存储的信息称为指针或链。这两部分信息组成结点(Node)。
n个结点链接成一个链表,即为线性表(a1,a2,a3.....,an)的链式存储结构。我们把链表中第一个结点称为头指针,最后一个节点指针为空(NULL)。如下图所示:
关于线性表的顺序存储和链式存储的区别,我想到一个例子来进行比喻。比如说我们去银行柜台办理银行卡和体育课站队列这两种情景。前者,在柜台办理业务时要去抽取一个号码,拿到号码之后只需要随意找个位子等着自己被叫号即可,那么不管顾客站在哪里等待,依然是按照顾客抽号的顺序来办理业务的,叫到自己的号码时便可以上前办理业务。后者,体育课上要按照身高排队列,排好之后如果有同学迟到晚来了,那么就根据他的身高来确定他要插入的位置,相应地,这位同学所处位置之后的同学就要往后移动一个位置。
假设p是指向线性表第i个元素的指针,则该结点ai的数据域我们可以用p->data的值是一个数据元素,结点ai的指针域可以用p->next来表示,p->next的值是一个指针。举个例子,如果p->data=ai,那么p->next->data=ai+1。
单链表读取元素的核心思想就是:工作指针后移。算法的时间复杂度依然取决于元素位置,如果在第一个位置那么时间复杂度为O(1),否则就要指针一个个后移直到找到那个元素。
易混淆的两个概念:头指针和头结点
头结点是指在单链表的第一个结点之前附设的一个结点。头结点的数据域可以为空也可以存储如线性表长度等的附加信息。头结点的指针域指向第一个结点的指针也就是第一个元素结点的存储位置。
单链表中可以没有头结点但是不能没有头指针,如果没有头结点则直接指向第一个结点。
相关文章推荐
- 数据结构
- 【专题小结】数据结构
- 数据结构-6
- SPOJ-LIS2[又遇CDQ]
- 数据结构堆的一种比较明白的讲解
- Java数据结构----树
- 《大话数据结构》之归并排序
- 数据结构与算法基础(二)之线性表的顺序存储
- 《数据结构》进行曲 之 单链表实现学生信息管理系统
- 《数据结构与算法分析(c描述》—— 快速排序
- golang实现常用数据结构
- 数据结构:散列(hashing)
- 大话数据结构--第2章 算法
- linux C 开发中重要的数据结构——结构体
- 数据结构与算法学习笔记(二)
- 慕课网----大话PHP设计模式 二(数据结构的php实现,链式操作,php魔方方法的使用)
- 算法竞赛入门经典(第二版)-刘汝佳-第六章 数据结构基础 习题(12/14)
- redis内部数据结构--简单动态字符串sds
- 数据结构-5
- 数据结构——二叉查找树