热度 21
2013-9-8 21:35
1724 次阅读|
1 个评论
数据结构学习笔记之线性表 1. 线性表 线性表是指:零个或多个数据元素的有限序列。 线性表的特点是:第一个元素无前驱,最后一个元素无后继。其他每个元素有且只有一个直接的前驱和后继。 线性表的长度是指包含数据元素的个数。 2. 线性表的抽象数据类型 线性表的的数据模型在定义中已经说明了,而线性表所包括的一组操作定义如下: 初始化 InitList(*L) 查询是否为空 ListEmpty(L) 清空 ClearList(*L) 获取线性表的第i个元素 GetElem(L,I,*e) 确定某个元素在线性表中的位置 LocateElem(L,e) 插入 ListInsert(*L,i,e) 删除 ListDelete(*L,i,*e) 返回线性表的长度 ListLength(L) 在实际的应用中,线性表的基本操作是不同的,可能是上面操作的一个子集。复杂的线性表操作可以由以上基本操作组合来实现。由之前的讨论可知,任何一种数据结构,有存储方式上,有顺序存储结构和链式存储结构。我们先从顺序存储结构讲起。 3. 线性表的物理存储结构 顺序存储结构 线性表的顺序存储结构是指用一段连续地址空间依次存储线性表的数据元素。在C语言中符合这种存储结构的数据类型是:数组。对,利用数组就可以存储线性表了。为了更好地抽象线性表,我们利用结构体的概念,将线性表的长度的属性也包括在这一结构体中。因此顺序存储结构的代码如下: # define MAXSIZE 20 # define OK 1 # define ERROR 0 # define TRUE 1 # define FALSE 0 typedef int Status; typedef int ElemType; typedef struct { ElemType data ; int length; }SqList; /*顺序存储结构包括3个关键因素:数组大小、链表长度以及数组起始地址*/ 接下来给出三个线性表相关操作的函数。代码实现如下: 获取线性表的第i个元素 GetElem(SqList L, int i, ElemType *e) Status GetElem(SqList L, int i, ElemType * e) { if (L.length == 0 || i 1 || i L.length) return ERROR; * e = L.data ; return OK; } 插入操作 ListInsert(SqList *L, int i, ElemType e) Status ListInsert(SqList * L, int i, ElemType e) { int k; if (L - length == MAXSIZE) return ERROR; if (i 1 || i L - length + 1 ) return ERROR; if (i L - length) { for (k = L - length;k i - 1 ;k -- ) { L - data = L - data ; } } L - data = e; L - length ++ ; return OK; } 删除操作 ListDelete(SqList *L, int i, ElemType *e) Status ListDelete(SqList * L, int i, ElemType * e) { int k; if (L - length == 0 ) return ERROR; if (i 1 || i L - length) return ERROR; * e = L - data ; if (i L - length) { for (k = i;k L - length;k ++ ) L - data = L - data ; } L - length -- ; return OK; } 顺序存储结构的优缺点如下: 优点:存储空间的利用率高,不用存储元素之间的逻辑关系。此外还能快速存取任意位置的元素,时间复杂度为O(1). 缺点:插入和删除操作需要移动大量元素,时间复杂度为O(1).容易造成存储空间“碎片”。 链式存储结构 鉴于顺序存储结构存在的缺点,链式存储结构采用了结点的方式来组织数据元素。结点包括数据域和指针域。其中数据域用来存储数据元素,指针域用来存储下一个结点的指针。这样就可以最大限度的利用存储空间,此外链式存储结构可以避免插入删除操作时的数据移动。 链表中的第一个结点的存储位置称为头指针。为了更方便的对链表进行操作,单链表的第一个结点前加一个结点,称为头结点。每一个链表都存在头指针,不一定存在头结点。头结点的数据域可以为空,也可以是链表长度信息,指针域为指向第一个结点。 下面简单介绍下链式存储结构的数据结构。其代码实现如下所示 typedef struct Node { ElemType data; struct Node * node; }Node typedef struct Node * LinkList; /*定义LinkList*/ 链式存储结构的单链表操作原理比较简单。主要是涉及到链表指针域的调整。 4. 单链表顺序结构与链式结构的优缺点比较 最后来来 总结 下顺序存储结构与链式结构。 若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。若需要频繁插入和删除时,宜采用单链表结构。 譬如,用于游戏账户的注册,可以考虑采用顺序存储结构,因为注册基本只需要一次插入操作,而需要较多的登录查询操作。 当线性链表中的元素个数变化较大或者不确定有多大时,最好采用单链表结构。