小猪的数据结构辅助教程——2.1 线性表中的顺序表
2015-12-08 21:57
525 查看
小猪的数据结构辅助教程——2.1 线性表中的顺序表
标签(空格分隔): 数据结构本节学习路线图与学习要点
![](http://7xjqvu.com1.z0.glb.clouddn.com/15-11-26/51013156.jpg)
学习要点:
1.抽象数据类型(ADT)的概念,三要素:数据,数据元素间的关系和数据的操作
2.线性表的特点:按照一条线排列的数据集合,1对1,除了首元和尾元,其他元素都有直接前驱和直接后继
3.牢记线性表的存储结构,要理解并熟悉12个基本操作的逻辑,最好能徒手撕出代码
4.求并集,顺序表的经典例子,必须掌握!
1.抽象的数据类型
![](http://7xjqvu.com1.z0.glb.clouddn.com/15-11-28/37807581.jpg)
简单点说:
抽象:有点像我们面向对象语言中的类的思想,将事物的共性抽取出来,形成属性和对应的方法!
数据类型:比如我们C中学的整型,浮点型等这些就是数据类型,就是具有同一性质的集合;
另外定义浮点类型是为了避免一些麻烦,比如保存2这个整数用浮点型就有点大材小用了~
2.线性表介绍以及顺序表的引入
![](http://7xjqvu.com1.z0.glb.clouddn.com/15-11-28/22165836.jpg)
从上面的存储结构,不难知道顺序表的三个属性:
存储空间的其实位置;最大存储容量listsize;当前长度length;
3.12个基本操作的代码实现
PS:别去死记代码,把逻辑掌握就好,不清楚自己列几个数据,画画图!线性表的存储结构
#define MAXSIZE 20 #define INCREMENT 10 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 //定义一个int数据类型的别名 //这里因为演示采用int,实际使用的通常是复合的数据类型 typedef int ElemType; typedef int Status; typedef struct{ ElemType *elem; //存储空间的起始地址 int length; //表的当前长度 int listsize; //表的总存储容量(以sizeof(ElemType)为单位) }SqList;
1.构造空表
void InitList(SqList *L){ L -> elem = (ElemType *)malloc(MAXSIZE * sizeof(ElemType)); if(!L -> elem)exit(ERROR); L -> length = 0; L -> listsize = MAXSIZE; }
步骤:
Step 1:申请表的存储空间,将空间的起始地址赋值给elem,
然后通过判断elem是否为空,从而知道内存是否分配成功
Step 2:将表的当前长度length设置为0,将表的大小listsize设置为MAXSIZE
2.将表置为空表
void ClearList(SqList *L) { L ->length = 0; }
步骤:
只需将表长设置为空即可,很简单
3.判断表是否为空
//3)判断表是否为空 Status ListEmpty(SqList L) { return L.length == 0?TRUE:FALSE; }
步骤:
只需判断表长是否为0即可
4.销毁表
//4)销毁表 void DestoryList(SqList *L) { free(L ->elem); L ->elem = NULL; L ->length = 0; L ->listsize = 0; }
步骤:
Step 1:调用free方法释放L.elem所指向的内存空间
Step 2:将L.elem赋值为NULL
Step 3:将当前的表长以及表的存储容量设置为0
5.获得表中元素的数目
int ListLength(SqList L) { return L.length; }
步骤:
直接返回当前表长度即可
6.获得表中第i个元素的值
Status GetElem(SqList L,int i,ElemType *e) { if(i < 1||i > L.length)return ERROR; e = *(L.elem + i - 1); return OK; }
步骤:
Step 1:先判断第i个位置是否合法
Step 2:将对应位置的值赋给e,另外这里减1是因为数组下标是从0开始算的,而我们看表是
从1开始算的,所以需要减一
7.查找表中是否有满足要求的元素
int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType)) { int i = 1; ElemType *p = L.elem; while(i < L.length && !compare(*p++,e)) i++; if(i <= L.length) return i; else return 0; }
步骤:
Step 1:定义变量i和指针p分别指向表中第1个元素和表的首地址
- Step 2:循环调用compare()函数与表中的元素进行比较
- Step 3:如果i <= length的话说明找到了,返回对应元素的序号
- Step 4:否则返回0,表示找不到满足要求的元素
8.返回某个节点的前驱
Status PriorElem(SqList L,ElemType choose,ElemType &Before){ int i = 2; ElemType *p = L.elem + 1; while(i < L.length && *p != choose) { p++; i++; } if(i > L.length)return ERROR; else { Before = *--p; return OK; } }
步骤:
Step 1:首元是没有直接前驱的,所以i应该从2开始,所以P从L.elem + 1开始;
Step 2:循环查看数据元素在表中的位置,如果i > 表长表示找不到,返回ERROR;
Step 3:找到的话,通过*–p获得该元素的前驱的值赋值给before;
9.返回某个节点的后继
Status NextElem(SqList L,ElemType choose,ElemType *behind) { int i = 1; ElemType *p = L.elem; while(i < L.length && *p != choose) { p++; i++; } if(i == L.length)return ERROR; else{ behind = * ++p; return OK; } }
步骤:
和前驱那个差不多,不过要注意i == L.length就到头了,因为尾元是没有后继的!
10.往表中第i个位置插入元素
Status ListInsert(SqList *L,int i,ElemType e) { ElemType *p,*q,*newbase; //判断插入位置是否合法 if(i < 1 || i > L -> length + 1)return ERROR; //假如表满了的话,增加分配的空间 if(L -> length == L -> listsize) { newbase = (ElemType *)realloc(L -> elem,(L -> listsize + INCREMENT)*sizeof(ElemType)); if(!newbase)exit(ERROR); L ->elem = newbase; L ->listsize += INCREMENT; } //插入位置 q = L ->elem + i - 1; //向右移,先移动最后一个 for(p = L ->elem + L->length - 1;p >= q;--p) { *(p + 1) = *p; } * q= e; //插入元素 ++ L ->length; //表长 + 1 return OK; }
步骤:
![](http://7xjqvu.com1.z0.glb.clouddn.com/15-12-2/24449922.jpg)
11.删除表中的第i个位置的元素
Status ListDelete(SqList *L,int i,ElemType *e) { ElemType *p,*q; //判断删除的位置是否合法 if(i < 1 || i > L ->length)return ERROR; //P指针指向删除位置,将要删除的元素赋值给e p = L ->elem + i - 1; e = *p; //q指针指向最后一个元素,从删除位置后的元素开始左移 q = L ->elem + L ->length - 1; for(++p;p <= q;++p) { *(p - 1) = *p; } L ->length--; //表长-1 return OK; }
步骤:
![](http://7xjqvu.com1.z0.glb.clouddn.com/15-12-2/3425203.jpg)
12.遍历表中的所有元素
void ListTraverse(SqList L,void(* visit)(ElemType)) { int i; ElemType *p = L.elem; for(i = 1;i < L.length;i++) { visit(*p++); printf("\n"); } }
步骤:
很简单,就是从第一个元素开始,指针后移动,依次调用visit()函数
实现表中元素的遍历而已
4.应用小示例:
问题:已知A,B两个顺序表中的元素是按从小到大排列的;现在要你求两个的并集C;
而且C中的元素也要按从小到大排序;不改变A和B中的数据!
是并集哦,就是C中不能有重复的元素
void UnionList(SqList La,SqList Lb,SqList *Lc) { //1.定义指向表A,B表头,表尾的指针 ElemType *la,*la_end,*lb,*lb_end,*lc; la = La.elem; lb = Lb.elem; la_end = La.elem + La.length - 1; lb_end = Lb.elem + Lb.length - 1; //2.为表C分配内存空间,大小为表A长度 + 表B的长度 Lc ->listsize = La.length + Lb.length; lc = Lc ->elem = (ElemType *)malloc(Lc ->listsize * sizeof(ElemType)); if(!lc)exit(ERROR); //3.将表A和B中的元素进行合并, while(la <= la_end && lb <= lb_end) { if(*la <= *lb)*lc++ = *la++; else *lc++ = *lb++; } //4.假如有剩余的元素,要么是表A,要么是表B的 while(la < la_end)*lc++ = *la++; while(lb < lb_end)*lc++ = *lb++; //5.接着要将C表中重复的元素删除掉,这里来两枚指针 ElemType *p,*q; p = Lc ->elem; q = p; //6.循环,假如入指针p没有指向表尾 while(p != (Lc ->elem + Lc ->length - 1)) { //q指向p的后继元素,比较两数的值 if(*p != *(++q)) { p++; q = p; } //相等的话,删除q所指向的元素 else { while(*p == *q); // ListDelete(Lc,(p - Lc ->elem),e); } } }
5.本节代码下载:
https://github.com/coder-pig/Data-structure-auxiliary-tutorial/blob/master/List/list1.c相关文章推荐
- 小猪的数据结构辅助教程——1.数据结构与算法绪论
- 小猪的数据结构辅助教程——前言
- 初学数据结构自己写的二叉树,方便以后看
- 数据结构练习题---括号匹配
- 二叉树三种遍历及删除和插入
- 数据结构-字符串
- 4阶b树与红黑树
- 数据结构与算法------二分查找
- 数据结构:Binary and other trees(数据结构,算法及应用(C++叙事描述语言)文章8章)
- 数据结构-C:二叉树的遍历
- 数据结构与算法------线性查找
- 数据结构与算法-----归并排序
- Huffman树及Huffman编码(数据结构)
- 数据结构实验之查找六:顺序查找
- 数据结构C++语言描述专题系列 (四) 链式栈和队列
- 主席树学习
- 数据结构实验之查找三:树的种类统计
- 【Codeforces Round 271 (Div 2)F】【贪心 线段树】Ant colony 区间段内是其他所有数因子的数的个数
- 【Codeforces Round 271 (Div 2)E】【离散化线段树】Pillars 最长连续序列使得序列相邻的数差值至少为k
- 数据结构C++语言描述专题系列 (三) 队列