第2章线性表与数组
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
线性表的顺序存储结构
动态分配的顺序存储结构介绍
由于存储分配只能预先进行,如果插入的数据量超出预先分配的存 储空间,要临时扩大有很大困难;如果按最大的可能空间进行分配, 势必降低了存储空间的利用率。为解决此问题,我们可以利用C语 言动态分配内存的机制,实现线性表的顺序存储。 #define INIT_SIZE 100 /*线性表存储空间的初始分配量 */ #define INCREMENT 10 /*线性表存储空间的分配增量 */ typedef struct { ELEMTP *elem /* 存储空间基址*/ int len; /*当前长度*/ int cursize; /*当前分配的存储容量*/ }DySqList;
– 数据域:元素本身信息 – 指针域:指示直接后继的存储位臵 数据域 指针域
例 线性表 (ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG)
存储地址
头指针 H 31 1 7 13 19 25 31 37 43
数据域 LI QIAN SUN
指针域 43 13 1
WANG WU ZHAO ZHENG ZHOU
线性表的逻辑结构
5. Insert(L,i,x); 在线性表L中第i个元素之前 (或之后)插入一个新元 素x; 6.Delete(L,i); 删除线性表L中的第i个元素;
由上述的基本操作,可以实现一些比较复杂的操作。例如:将两个 线性表合并成一个线性表;把一个线性表拆成两个线性表等。
线性表的顺序存储结构
• 缺点
– 插入、删除操作需要移动大量的元素 – 预先分配空间需按最大空间分配,利用不充分 – 表容量难以扩充
2.3 线性表的链式存储结构
特点:
• 用一组任意的存储单元存储线性表的数据元素 • 利用指针实现了用不相邻的存储单元存放逻辑上相邻的元 素 • 每个数据元素ai,除存储本身信息外,还需存储其直接后 继的信息 • 结点 结点
头结点:在单链表第一个结点前附设一个结点叫~ 头结点指针域为空表示线性表为空
头结点 h a1
a2 …... an ^
h
^
空表
线性表的链式存储结构
单链表的基本操作
查找单链表中第i个结点
在单链表中查找某结点,需要设臵一个指针变量从头指针出发,逐
步向后移动查找,查找到则返回该指针值,否则返回空指针。
线性表小结
线性结构特点:在数据元素的非空有限集中
存在唯一的一个被称作“第一个”的数据元素 存在唯一的一个被称作“最后一个”的数据元素 除第一个外,集合中的每个数据元素均只有一个前驱 除最后一个外,集合中的每个数据元素均只有一个后 继
顺序存储结构的优缺点
• 优点
– 逻辑相邻,物理相邻 – 可随机存取任一元素 – 存储空间使用紧凑
线性表的顺序存储结构
删除
删除操作是指删除线性表的第i个数据元素,这时只需将ai+1,... an 依次向前移动一个位臵,这样元素ai 即已被删除。
原来长度为n的线性表(a1,...,ai-1,ai,..., an)变成长度为n-1 的线性表(a1,...,ai-1,ai,...,an-1)。
顺序存储结构
线性表的顺序存储指的是用内存中一批地址连续的存储单元依次存 储线性表中的数据元素。如图2-2-1所示。它的特点是线性表中相邻 的元素在内存中的存储位臵也是相邻的。由于线性表中的所有数据 元素属于同一类型,所以每个元素在存储器中所占的空间大小相同。 线性表的顺序存储结构是一种随机存取的存储结构。这是顺序存储 结构的一个重要特点。
线性表的顺序存储结构
基本操作的实现
插入
插入操作是指在线性表的第i-1个数据元素和第i个数据元素之间插 入一个新的数据元素x,使长度为n的线性表(a1,...,ai-1,ai,..., an)变成长度为n+1的线性表(a1,...,ai-1,x,ai,...,an+1)。 插入时首先将线性表中原来元素ai,ai+1,... ,an从an起依次向后 移动一个位臵,然后在位臵i上插入新元素x。 在实现操作时,还应注意对插入位臵的合理性、表是否已满等特殊 情况的处理。
线性表的顺序存储结构
从插入和删除算法可见,当在顺序存储结构的线性表中某个位臵上插入或 删除一个元素时,其时间主要耗费在移动元素上,而移动元素的个数取决 于插入或删除元素的位臵。 假设pi是在第i个元素之前插入一个元素的概率,则在长度为n的线性表中 插入一个元素时所需移动元素次数的平均次数为:
由算法可以看出,基本操作是比较j和i并移动p,while循环体中的 语句频度与被查元素在表中的位臵有关,若1≤i≤表长n,则频度为i1,否则频度为n。因此算法的时间复杂度为0(n)。 同时,我们 也看到整个链表的存取必须从头指针H开始进行,因此单链表是一 种非随机存取的存储结构。
NULL 37 7 19 25
H ZHAO ZHOU QIAN SUN ZHENG
LI
WANG
WU
^
线性链表
• 定义:结点中只含一个指针域的链表叫~,也叫单链表
• 实现
typedef struct node { ElemType data; struct node *next; } LNode LNode;
线性表的顺序存储结构
初始化线性表:指的是为顺序表分配一个预定义的存储空间,并将 线性表的当前长度定义为零。分配一个预定义的存储空间可以通过 调用C语言的动态分配库函数malloc来实现。 算法 2.3 int Init_List(DySqList *L){ /*构造一个空的线性表L*/ L->elem= (ELEMTP *) malloc(INIT_SIZE * sizeof(ELEMTP)); /*分配存储空间*/ if(!L->elem) exit(0); /*存储分配失败*/ L->len=0; /*空表长度为0*/ L->cursize= INIT_SIZE; /*初始存储容量*/ return 1; }/* Init_List */
线性表的逻辑结构
线性表的基本操作
线性表是一种灵活的数据结构,其表长可根据不同的操作增长或缩 短。
1.InitList(L); 建立一个空的线性表L;
2.GetElem(L,i); 取线性表L中的第i个元素; 3.Length(L); 求线性表L的长度; 4.Locate(L,x); 确定元素x在线性表L中位臵;
LNode *h,*p; data p next (*p)表示p所指向的结点 (*p).datap->data表示p指向结点的数据域 (*p).nextp->next表示p指向结点的指针域
结点(*p)
生成一个LNode型新结点:p=(LNode *)malloc(sizeof(LNode)); 系统回收p结点:free(p)
线性表的顺序存储结构
算法2.1 【演示】 int Insert_Sq (SqList *L ,int i, ELEMTP x) /* 在线性表的第i-1和第i元素之间插入一个新元素x*/ { if (i<1 || i>L->len+1) return 0; /* 不合理的插入位臵 i */ if ( L->len== MAXSIZE-1) return -1; /* 表已满 */ for (j=L->len;j>=i;--j) L->elem[j+1]=L->elem[j]; /* 插入位臵及之后的元素右移*/ L->elem[i]=x; /*插入x */ ++L->len; /*表长加1 */ return 1; } /* Insert_Sq */
在高级语言中讨论线性表的顺序存储结构,通常是利用数组来进行 描述,它是最直观的方法。由于对线性表wenku.baidu.com要进行插入和删除操作, 因此其长度是变化的。
线性表的顺序存储结构
图2-2-1 线性表的顺序存储结构示意图
线性表的顺序存储结构
在图2-2-1中, 假设第一个元素存放的位臵为LOC(a1),每个元素占 用的空间大小为L,则元素ai的存放位臵为: LOC(ai)=LOC(a1)十L*(i-1) 线性表的顺序存储结构可定义为: typedef struct { ELEMTP elem[MAXSIZE]; /*存储线性表中的元素*/ int len; /*线性表的当前表长*/ }SqList;
线性表的顺序存储结构
插入:算法思路与算法 2.1类似。只是当存储空间已满时,可以通 过调用C语言的动态分配库函数realloc来增加存储空间,从而实现 线性表的可扩充性。 删除算法与插入算法类似,在此不再细述。
线性表的顺序存储结构
算法 2.4
int Insert_DySq (DySqList *L ,int i, ELEMTP x) /* 在动态分配的顺序表的第i-1和第i元素之间插入一个新元素x*/ { if (i<1 || i>L->len+1) return 0; /* 不合理的插入位臵 i */ if ( L->len >= L-> cursize){ /* 当前存储空间已满,增加分配 */ new=(ELEMTP *) realloc(L->elem, (L->cursize+ INCREMENT) * sizeof(ELEMTP)); if(!new) exit(0); /* 存储分配失败*/ L->elem=new; /*新基址*/ L->cursize+=INCREMENT; /*增加后的存储空间 */ } q=L->elem[i-1]; /*q为插入位臵*/ for (p=L-elem[L->len-1];p>=q;--p) *(p+1)= *p; /* 插入位臵及之后的元素右移*/ *q=x; /*插入x */ ++L->len; /*表长加1 */ return 1; }/* Insert_DySq */
线性表的顺序存储结构
算法2.2 【演示】 int Delete_Sq (SqList *L ,int i ) /* 删除线性表中第个i元素 */ { if (i<1 || i>L->len) return 0; /*不合理的删除位臵 i */ if (L->len==0) return -1; /* 表已空*/ for (j=i;j<=L->len-1;j++) L->elem[j]=L->elem[j+1]; /*被删除元素之后的元素左移 */ --L->len; /*表长减1*/ return 1; }/* Delete_Sq */
线性表的顺序存储结构
假设qi是删除第i个元素的概率,则在长度为n的线性表中删除一个元素时 所需移动元素次数的平均次数为:
如果在表的任何位臵上插入或删除元素的概率相等,即: 那么:
线性表的顺序存储结构
可见,在顺序存储结构的线性表中插入或删除一个元素时,平均约移动表 中的一半元素,若表长为n,则上述算法的时间复杂度均为O(n)。 除了上述两种基本操作外,还有一些较为复杂的运算,比如在非递减有序 表中插入一个数据元素x,使线性表仍保持非递减有序;在非递减有序表 中删除所有值为x的元素等等,在这里就不作介绍了。
表中的元素可以是一个数,一个符号或是由多个数据项组成的复杂 信息,但同一线性表中的元素必须属于同一数据对象。例如,英文 字母表:(A,B,C,D,…,X,Y,Z)和表2-1-1的学生登记表 都是线性表。
线性表的逻辑结构
线性表的逻辑结构是通过元素之间的相邻关系体现的:a1为开始结 点 , an 为 终 端 结 点 ; ai-1 为 ai 的 直 接 前 趋 结 点 (predecessor) (2≤i≤n);ai+1为ai的直接后继结点(successor) (1≤i≤n-1) 。线 性表中元素的个数(n)称为该表的长度。长度为零(n=0)的表 称为空表
数据结构
第2章 线性表和数组
第2章 线性表和数组
线性表的逻辑结构
线性表的顺序存储结构
线性表的链式存储结构
循环链表和双向链表
线性表的应用——多项式相加问题
数组
线性表的逻辑结构
线性表的定义
线性表是n(n≥0)个数据元素组成的有限序列。一般记作: L=( a1,a2,…,ai,…,an)