第2讲 顺序表
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2. 求表长操作 (统计顺序表L中存储的数据元素个数) int getlen(sqlist L) { return(L.length); }
3. 取元素操作 (取出顺序表L的第i个数据元素的值) int getelem(sqlist L,int i,ElemType *e) { if(i<1||i>L.length) return 0; /* 取元素失败 */ *e=L.data[i-1]; return 1; /* 取元素成功 */ }
• 【例2】编写算法,将两个非递减顺序表L1 和L2合并到顺序表L中,使合并后的顺序表 仍然保持非递减的特性。 • 算法思路:从两个顺序表的第一个元素开 始进行比较,若L1->data[i]≤L2->data[j], 将L1->data[i]插入到L的尾部,否则将L2>data[j]插入到L的尾部;循环这个过程,直 到有一个表中的所有元素均已插入到L中为 止;再把另一个表的剩余部分依次接到L的 尾部。
第2讲 顺序表及基本操作
•掌握:线性表的定义、线性表的基本操 掌握: 掌握 作、顺序表的类型定义、初始化、求长、 取元素、查找定位、插入、删除、输入、 插入建表。 •重点:顺序表的基本操作实现 重点: 重点 •难点:插入和删除操作 难点: 难点 •特点:逻辑上相邻的元素在物理地址上 特点: 特点 一定相邻!!!
一、线性表的定义及基本操作
1. 线性表的定义 线性表(liner_List):是n(n≥0)个数据元素 a1,a2,…, an组成的有限序列,记为 L=(a1,a2,…,an) 其中,L是线性表的名称。数据元素的个数n称为 线性表的长度,若n=0,则称为空表。 若线性表非空,则ai(1≤i≤n)称作线性表的第i个 元素,i称为ai的位序。a1,a2,…ai-1称作ai(1<i≤n) 的前驱,其中,ai-1称作ai的直接前驱; ai+1,ai+2,…an称作ai(1≤i<n)的后继,其中, ai+1称作ai的直接后继。
二、顺序表的定ຫໍສະໝຸດ Baidu及基本操作实现
1. 顺序表的定义 逻辑上相邻接的数据元素存储在物理地址上也相邻接 的存储单元中,这种存储结构称为顺序存储结构,用顺序 存储结构存储的线性表就称为顺序表。 2. 顺序表中的元素地址计算 假设顺序表(a1,a2,…,an)的每个元素占用k个字节,且第i 个元素ai的存储地址用LOC(ai)表示,则相邻元素的存 储地址有下列关系: LOC(ai)=LOC(ai-1)+k (2≤i≤n) 由此可得: LOC(ai)=LOC(a1)+(i-1)*k (1≤i≤n) 其中,LOC(a1)是第一个元素的起始地址,通常称为顺序 表的起始地址或基地址,也简称为基址。
6. 删除操作 (将顺序表L的第i个元素删除) • 算法思路:在长度为n的顺序表中删除一个 数据元素时,首先确定删除位置i的合法性 (1≤i≤n)。若参数i合法,则从位序为i+1的数 据元素开始,把位序为i+1,i+2,…,n的数据 元素依次移到位序为i,i+1,…,n-1的位置上 即可。
int delete(sqlist *L,int i,ElemType *e) { int j; if(i<1||i>L->length) return 0; /* 无效的参数i,返回0 */ *e=L->data[i-1]; /* 存储被删除的元素 */ for(j=i;j<L->length;j++) L->data[j-1]=L->data[j]; /* 将序号为i的结点及之后的结点前移一位 */ L->length--; /* 顺序表长度减1 */ return 1; /* 删除成功,返回1 */ }
int insert(sqlist *L,int i,ElemType x) { int j; if(i<1||i>L->length+1) return 0; /* 无效的参数i,返回0 */ if(L->length==L->listsize) /* 存储空间不够,增加一个存储空间 */ { L->data=(ElemType *)realloc(L->data, (L->listsize+1)*sizeof(ElemType)); L->listsize++; /* 重置存储空间长度 */ } for(j=L->length-1;j>=i-1;j--) L->data[j+1]=L->data[j]; /* 将序号为i的结点及之后的结点后移一位 */ L->data[i-1]=x; /* 在序号i处放入x */ L->length++; /* 顺序表长度增1 */ return 1; /* 插入成功,返回1 */ }
3. 顺序表的类型定义 typedef int ElemType; /* 在实际问题中,根据需要定义所需的数据类型 */ #define INITSIZE 100 /* 顺序表存储空间的初始分配量 */ typedef struct { ElemType *data; /* 存储空间基地址 */ int length; /* 顺序表长度(已存入的元素个数) */ int listsize; /* 当前存储空间容量(能存入的元素个数) */ }sqlist;
• 【例1】已知顺序表L中存放的是互不相同 的整数,编写算法,将顺序表L中的所有奇 数移到所有的偶数(含0)前面。要求时间最 少,辅助空间最少。 • 算法思路:从头向尾找到偶数L->data[i], 再从尾向头找到奇数L->data[j],然后将两 者交换;循环这个过程,直到i大于或等于j 为止。
7. 输出操作 (输出顺序表L的各数据元素值) void list(sqlist L) { int i; for(i=0;i<L.length;i++) printf("%5d ",L.data[i]); printf("\n"); }
8. 插入建表操作 (利用尾接的方法建立有初始数据的顺序表) void input(sqlist *L,int n) { int i; ElemType x; for(i=1;i<=n;i++) { scanf(“%d”,&x); /* 键盘读入n个数据 */ insert(L,i,x); /* 插入到顺序表的尾部 */ } }
4. 元素定位操作 (在顺序表L中,查找第1个与x值相等的数据元素的位置) • 算法思路:从顺序表L的第一个元素开始,逐个进行给定 值x和数据元素值的比较,若某个数据元素的值和给定值x 相等,则返回该数据元素的位序;若直到最后一个数据元 素,其值和x值都不相等,则返回0。 int locate(sqlist L,ElemType x) { int i=0; /* 置初始下标值0 */ while(i<L.length) if(L.data[i]==x) return i+1; /* 找到返回位序i+1 */ else i++; /* 没找到,继续向下查找 */ return 0; /* 没找到,返回0 */ }
三、基本操作在顺序表上的实现
1. 初始化操作(创建一个空的顺序表L) void initlist(sqlist *L) { L->data=(ElemType*) malloc(sizeof(ElemType)*INITSIZE); /*存储空间的初始量*/ L->length=0; /* 长度为0 */ L->listsize=INITSIZE; /* 当前容量为初始量 */ }
5. 插入操作 (在顺序表L中的第i个位序上插入一个值为x 的数据元素) • 算法思路:在长度为n的顺序表中插入一个 数据元素时,首先确定插入位置i的合理性 (1≤i≤n+1)。若参数i合理,则从位序为n的 数据元素开始,把位序为n,n-1,…,i的数据 元素依次移到位序为n+1,n,…,i+1的位置 上,空出第i个位置,在该位置上存入值为x 的数据元素。
void move(sqlist *L) { int i=0,j=L->length-1; ElemType temp; while(i<j) { while(i<j&&L->data[i]%2!=0) i++; /* 从头向尾找到偶数 */ while(i<j&&L->data[j]%2==0) j--; /* 从尾向头找到奇数 */ if(i<j) /* 交换 */ { temp=L->data[i]; L->data[i]=L->data[j]; L->data[j]=temp; } } }
2. 线性表的基本操作 (1) 初始化操作initlist(L), 其作用是建立一个空的线性表L。 (2) 求表长操作getlen(L),其作用是返回线性表L的长度。 (3) 元素定位操作locate(L,x),其作用是返回元素x在线性表L 中第一次出现的位置,若x存在,则返回其位序,否则, 返回0。 (4) 取元素操作getelem(L,i,e),其作用是返回线性表L中的第 i个元素的值,并送给e。i的合理取值范围为:1≤i≤n。 (5) 插入操作insert(L,i,x),其作用是在线性表L的第i个位置上 插入一个值为x的元素。i的合法取值范围是:1≤i≤n+1。 (6) 删除操作delete(L,i,e),其作用是删除线性表L中的第i个 元素,并送给e。i的合理取值范围是:1≤i≤n。 (7) 输出操作list(L),其作用是按先后顺序输出线性表L中的 所有元素。
void merge(sqlist L1,sqlist L2,sqlist *L) { int i=0,j=0; initlist(L); /* 初始化顺序表L */ while(i<L1.length&&j<L2.length) if(L1.data[i]<L2.data[j]) /* 将L1.data[i]插入到L尾部 */ { insert(L,L->length+1,L1.data[i]);i++;} else /* 将L2.data[j]插入到L的尾部 */ { insert(L,L->length+1,L2.data[j]);j++;} while(i<L1.length) /* L2中的元素已插完,将L1的剩余部分插入到L尾部 */ { insert(L,L->length+1,L1.data[i]);i++;} while(j<L2.length) /* L1中的元素已插完,将L2的剩余部分插入到L尾部 */ { insert(L,L->length+1,L2.data[j]);j++;} } • 作业:P79-4(1)、(4)。 • 掌握顺序表的存储、插入和删除元素的方法。 掌握顺序表的存储、插入和删除元素的方法。