线性表知识结构图
线性表的类型定义、顺序表示和实现
i=n 只删 an即可 1≤i≤n -1 将ai+1 ~an前移
23
bool deleteElem(SqList& L,int pos)
typedef int ElemType;
typedef char ElemType;
等;
②同一线性表中的数据元素必须具有相同的特性,属同一类 型;
③a2,关…系, ra是i-1,一a个i, a有i+1序, …偶,对an的)集,合a,i-1即领对先于于非ai,空表的示线了性数表据(元a1,素 之间的相邻关系,称ai-1是ai的直接前驱,ai是ai-1的直接后继 ;
6
2.1.3 操作举例
例:假设利用两个线性表La和Lb分别表示两 个集合A和B,求一个新的集合A=A∪B。
算法:
– ①取得Lb中的1个元素; – ②在La中查找这个元素; – ③若不存在:插入La中;若存在,取Lb中下一个
元素,重复 ①、②、③,直到取完Lb的每个元素 。
7
void unionList(SqList &la,SqList lb)
10
线性表的顺序存储结构示意图
存储地址
loc(a1) loc(a1)+ k
内存空间状态 逻辑地址
a1
1
a2
2
…
…
…
loc(a1)+ (i- 1)k
ai
i
…
…
…
loc(a1)+ (n- 1)k
an
n 空闲
顺序存储结构可以借助于高级程序设计语言中的一维数组来表示。
11
用C++语言描述的顺序表类型如下所示: sqlist.h
数据结构第1讲---线性表
34F2 地址 被释放,变 量P与地址 34F2没有关 系
p1^
200 34F2
34F2
new(p1) ——向计算机申请内存地址 p1^:=200 ——给p1指向的单元赋值 dispose(p1) ——释放存储单元
链式结构——什么是指针
Type p=^integer; arr=array[1..4] of char; arrp = ^arr; Var p1:p; p2:arrp;
线性结构 数据的逻辑结构 数 据 结 构 树形结构 图形结构 数据的存储结构 顺序存储
链式存储
数据结构的基本运算 :查找、插入、删除等
三、线性结构——线性表
1、线性表的概念
线性表是由n(n≥0)个具有相同特性数据元素(结点)
a1,a2,…,an组成的有限序列。
线性表的长度:所含元素的个数,用n表示,n>=0。
在我们生活中有哪些属于线性表的例子,列举几个。 1、英文字母表(A,B,…,Z)是线性表, 表中每个字母是一个数据元素(结点)
2、学生成绩表中,每个学生及其成绩是一
个数据元素,其中数据元素由学号、姓名、
各科成绩及平均成绩等数据项组成。
4、线性表的顺序存储
顺序存储是线性表的一种最 简单的存储结构,存储方式是: 在内存中为线性表开辟一块连 续的存储空间。用数组来存放 每一个节点。
[例4-2] 法雷序列
[问题描述]对任意给定的一个自然数n(n<=100),将 分母小于等于n的不可约的真分数按上升次序排序,并 且在第一个分数前加0/1,而在最后一个分数后加1/1, 这个序列称为n级的法雷序列。 当n=8时序列为:0/1, 1/8, 1/7, 1/6,1/5, 1/4,2/7,1/3,3/8, 2/5,3/7,1/2,4/7,3/5,5/8,2/3,5/7,3/4, 4/5,5/6,6/7,7/8, 1/1 。 编程求出n级的法雷序列,每行输出10个分数。
线性表
2.1 线性表的类型定义
例3:下图为10个个学生的成绩表,它也是一个 线性表,该线性表的数据元素类型为结构体类型。
2.1 线性表的类型定义
从以上例子可看出线性表的逻辑特征是: 在非空的线性表中,有且仅有一个被称作 “第一个”的数据元素a1,它没有直接前趋, 而仅有一个直接后继a2; 有且仅有一个被称作“最后一个”的数据元 素an,它没有直接后继,而仅有一个直接前 趋 a n-1; 其余的数据元素ai(2≦i≦n-1)都有且仅有一个 直接前趋a i-1和一个直接后继a i+1。 线性表是一种典型的线性结构。
2.2 线性表的顺序表示和实现
#define MAXNUM 100 Elemtype List1[MAXNUM] ; /*定义线性表L1*/ int length1;
Elemtype List2[MAXNUM] ; /*定义线性表L1*/ int length2;
Elemtype List3[MAXNUM] ; /*定义线性表L1*/ int length3;
2.2 线性表的顺序表示和实现
而只需要将数组和表长封装在一个结构体中,然 后定义三个结构体变量即可: struct L_list { Elemtype List[MAXNUM]; int length; }; struct L_list L1, L2, L3; /*定义三个线性表L1,L2,L3*/
2.1 线性表的类型定义
例1:26个英文字母组成的字母表 (A,B,C、…、Z) 例2:某公司2000年每月产值表(单位:万元) (400,420,500,…,600,650) 是一个长度为12的线性表。
上述两例中的每一个数据元素都是不可分割的, 在一些复杂的线性表中,每一个数据元素又可 以由若干个数据项组成。
线性表的顺序存储结构
∑
n +1 i =1
p i ( n i + 1)
1 不失一般性,若在线性表的任何位置插入元素都是等概率的,即 p i = 不失一般性,若在线性表的任何位置插入元素都是等概率的, , n + 1 上式可化简为: 上式可化简为: 1 n+1 n
Eis =
∑(n i +1) = 2 n +1
第二章 线性表
2.1 线性表的类型定义 2.2 线性表的顺序表示和实现
2.3 线性表的链式表示和实现
2.4 一元多项式的表示及相加
2.2 线性表的顺序表示和实现 线性表的顺序表示指的 是用一组地址连续的存储单 元依次存储线性表的数据元 素.
£2.2 线性表的顺序存储结构
(1)线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性 ) 表的数据元素.如下图2.1所示 所示: 表的数据元素.如下图 所示: 存储地址 b b+l … b+(i-1)l … b+(n-1)l b+nl … b+(maxlen-1)l 内存状态 a1 a2 … ai … an 空闲 数据元素在线性表中的位序 1 2 … i … n
// 为顺序表分配大小为 maxsize 的数组空间
if (!L.elem) exit(OVERFLOW); L.length = 0; L.listsize = maxsize; return OK; 算法时间复杂度 O(1) 时间复杂度: 时间复杂度 } // InitList_Sq
(4)线性表的插入和删除运算 ) 序号 数据元素 1 2 3 4 5 6 7 8 12 13 21 24 28 30 42 77 (a) 序号 数据元素 1 2 3 4 5 6 7 8 9 12 13 21 24 25 28 30 42 77 (b) 序号 数据元素 1 2 3 4 5 6 7 8 12 13 21 24 28 30 42 77 (a) 序号 数据元素 1 2 3 4 5 6 7 12 13 21 28 30 42 77
数据结构 线性表
(9) Status NextElem_Sq(SqList L, ElemType cur_e, ElemaType &next_e)
//若cur_e是线性表L的元素且不是最后一个,返回它的后继 { for (i=0; i<L.length-1; i++) if (cur_e==L.elem[i]) { next_e=L.elem[i+1]; return OK; } return ERROR; }//NextElem_Sq O(n)
抽象数据类型 唯 一 数据的逻辑结构 确 操作的定义 定
集合 *
线性表
特殊线性表 扩展线性表
线性结构
树形结构 图形结构
灵 活 数据的存储结构 操作的实现 设 计
顺序存储 链式存储 散列(哈希)存储
数据的基本操作:针对结构、针对元素、针对状态
数据结构---第二章 线性表 1
第二章 线性表
2.1 2.2 2.3 2.4
数据结构---第二章 线性表
9
2.2 线性表的顺序存储结构(顺序表)
起始地址为b、最多可容纳maxlen个元素的线性表
下标 存储地址
0
1
b b+c
b+(i-1)c
a1 a2
ai
c个存储单元
i-1
LOC(ai)=LOC(a1)+(i-1)c LOC(ai)=LOC(ai-1)+c
n-1
b+(n-1)c
n-1
int LocateElem_Sq(SqList L, ElemType e, (7) Status (*compare)(ElemType,ElemType) ) //在线性表L中查找第1个值与e满足 //compare()的元素的位序 { for (i=0; i<L.length; i++) L.elem[i]==e if ( (*compare)(L.elem[i],e) ) return i+1; return 0 ; //作为未找到的特殊标记 } // LocateElem_Sq O(n) P25-2.6
数据结构-线性结构
数据结构-线性结构线性表线性表是最简单最常见的数据结构,属于逻辑结构;线性表有两种实现⽅式(存储⽅式),分别是顺序实现和链接实现;定义:线性表是由n(>=0)个数据元素组成的有限序列,数据元素的个数n定义为表的长度;术语:前驱, 后继, 直接前驱, 直接后继, 长度, 空表案例:线性表⽤L表⽰,⼀个⾮空线性表可记为L = (a1,a2,..an);a1后⾯的称为a1的后继an前⾯的称为an的前驱a1为起始节点,an为终端节点,任意相邻的两个元素,如a1和a2,a1是a2的直接前驱,a2是a1的直接后继;线性表中元素个数即表的长度,此处为n;表中没有任何元素时,称为空表除了⾸节点和尾节点之外,每个节点都有且只有⼀个直接前驱和直接后继,⾸节点没有前驱,尾节点没有后继;节点之间的关系属于⼀对⼀;线性表的基本运算初始化Initiate(L) 建⽴⼀个空表L(),L不包含数据元素求表长度Length(L) 返回线性表的长度取表元素Get(L,i) 返回线性表的第i个元素,i不满⾜1<=i<=Length(L)时,返回特殊值;定位Locate(L,x)查找x在L中的节点序号,若有多个匹配的返回第⼀个,若没有匹配的返回0;插⼊Insert(L,x,i)将x插⼊到L的第i个元素的前⾯(其他元素往后挪),参数i取值范围为1<=i<=Length(L)+1;运算结束后表长度+1;删除Delete(L,i)删除表L中的第i个元素,i有效范围1<=i<=Length(L);操作结束后表长度-1强调:上述的第i个指的是元素的序号从1开始,⽽不是下标从0开始;另外:插⼊操作要保证操作后数据还是⼀个接着⼀个的不能出现空缺;线性表的顺序存储实现线性表是⼀种逻辑结构,可以通过顺序存储结构来实现,即:将表中的节点⼀次存放在计算机内存中⼀组连续的存储单元中,数据元素在线性表中的邻接关系决定了它们在存储空间中的存储位置;换句话说逻辑结构中相邻的两个节点的实际存储位置也相邻;⽤顺序存储结构实现的线性表也称之为为顺序表,⼀般采⽤数组来实现;图⽰:⼤⼩与长度:线性表的⼤⼩:指的是最⼤能存储的元素个数线性表的长度:指的是当前已存储的个数⽰例:c语⾔实现:#include <stdio.h>//初始化操作:const MAX_SIZE = 5;//最⼤长度typedef struct list {int data[MAX_SIZE];//数组int length;//当前数据长度};//获取targert在表中的位置int locate(struct list *l,int target){for (int i = 0;i < l->length;i++){if (target == l->data[i]){return i + 1;}}return 0;}//获取第loc个元素int get(struct list *l,int loc){if (loc < 1 || loc > l->length){printf("error:位置超出范围\n");return -1;}else{return l->data[loc-1];}}//插⼊⼀个元素到第loc个位置上void insert(struct list *l,int data,int location){if (l->length == MAX_SIZE){printf("errolr:表容量已满\n");return;}if (location < 1 || location > l->length+1){printf("error:位置超出范围\n");return;}//⽬标位置后⾯的内容以此往后挪for (int i = l->length; i >= location; i--) {l->data[i] = l->data[i-1];}//在⽬标位置放⼊新的数据l->data[location-1] = data;l->length+=1;//长度加1}//删除第loc个元素,从⽬标位置往后的元素⼀次向前移动void delete(struct list *l,int loc){if (loc < 1|| loc > l->length){printf("error:位置超出范围\n");return;}//⽬标位置及后⾯的所有元素全部向后移动for (;loc < l->length; ++loc) {l->data[loc-1] = l->data[loc];}l->length-=1;}//打印所有元素测试⽤void show(struct list l){for (int i = 0; i < l.length; ++i) {printf("%d\n",l.data[i]);}}//测试int main() {struct list alist = {};insert(&alist,100,alist.length+1);insert(&alist,200,alist.length+1);insert(&alist,300,alist.length+1);insert(&alist,400,alist.length+1);delete(&alist,1);printf("%d\n",alist.length);show(alist);printf("%d\n",get(&alist,4));printf("%d\n", locate(&alist,300));printf("%d\n", get(&alist,1));return 0;}插⼊算法分析:假设线性表中含有n个元素,在插⼊元素时,有n+1个位置可以插⼊,因为要保证数据是连续的每个位置插⼊数据的概率是: 1/(n+1)在i的位置插⼊时,要移动的元素个数为:n - i + 1算法时间复杂度为:O(n)删除算法分析:假设线性表中含有n个元素,在删除元素时,有n个位置可以删除每个位置插⼊数据的概率是: 1/n在i的位置删除时,要移动的元素个数为:n - i算法时间复杂度为:O(n)插⼊与删除的不⾜顺序表在进⾏插⼊和删除操作时,平均要移动⼤约⼀半的数据元素,当存储的数据量⾮常⼤的时候,这⼀点需要特别注意;简单的说,顺序表在插⼊和删除时的效率是不够好的;特别在数据量⼤的情况下;顺序表总结:1.顺序表是⼀维数组实现的线性表2.逻辑上相邻的元素,在存储结构中也是相邻的3.顺序表可实现随机读取优缺点:优点:⽆需为了表⽰元素直接的逻辑关系⽽增加额外的存储空间可⽅便的随机存取表中的任⼀节点缺点:插⼊和删除运算不⽅便,需要移动⼤量的节点顺序表要求占⽤连续的存储空间,必须预先分配内存,因此当表中长度变化较⼤时,难以确定合适的存储空间⼤⼩;顺序表节点存储地址计算:设第i个节点的存储地址为x设顺序表起始地址为loc,每个数据元素占L个存储单位计算公式为:x = loc + L * (i-1)如 loc = 100 i = 5 L = 4 则 x = 116线性表的链接存储实现线性表也可通过链接存储⽅式来实现,⽤链接存储⽅式实现的线性表也称为链表 Link List链式存储结构:1.可⽤任意⼀组存储单元来存储数据2.链表中节点的逻辑次序与物理次序不⼀定相同3.每个节点必须存储其后继节点的地址信息(指针)图⽰:单链表单链表指的是只能沿⼀个⽅向查找数据的链表,如上图每个节点由两个部分(也称为域)组成data域存放节点值得数据域next域存放节点的直接后继的地址的指针域(也称为链域)节点结构:每个节点只知道⾃⼰后⾯⼀个节点却不知道⾃⼰前⾯的节点所以称为单链表图⽰:带有head节点的单链表:单链表的第⼀个节点通常不存储数据,称为头指针,使⽤头指针来存储该节点的地址信息,之所以这么设计是为了⽅便运算;单链表特点:其实节点也称为⾸节点,没有前驱,所以头指针要指向该节点,以保证能够访问到起始节点;头指针可以唯⼀确定⼀个链表,单链表可以使⽤头指针的名称来命名;终端节点也称尾节点,没有后继节点,所以终端节点的next域为NULL;除头结点之外的⼏点称为表结点为⽅便运算,头结点中不存储数据单链表数据结构定义//数据结构定义typedef struct node {struct node *next;int data,length;} Node, *LinkList;/** typedef 是⽤来取别名的* Node 是struct node 的别名* *LinkList 是 struct node *的别名* 后续使⽤就不⽤在写struct关键字了*/运算:初始化⼀个空链表有⼀个头指针和⼀个头结点构成假设已定义指针变量L,使L指向⼀个头结点,并使头结点的next为NULL//时间复杂度 :O(1)LinkList initialLinkList() {// 定义链表的头结点LinkList head;//申请空间head = malloc(sizeof(struct node));//使头结点指向NULLhead->next = NULL;return head;}求表长从头指针开始遍历每个节点知道某个节点next为NULL为⽌,next不为空则个数len+1;//求表长时间复杂度 :O(n)int length(LinkList list){int len = 0;Node *c = list->next;while(c != NULL){len+=1;c = c->next;}return len;}读表元素给定⼀个位置n,获取该位置的节点遍历链表,过程中若某节点next为NULL或已遍历个数index=n则结束循环//从链表中获取第position个位置的节点时间复杂度 :O(n)Node *get(LinkList list, int position) {Node *current;int index = 1;current = list->next;//如果下⾯还有值并且还没有到达指定的位置就继续遍历要和查找元素区别开这就是⼀直往后遍历直到位置匹配就⾏了 while (current != NULL && index < position) {current = current->next;index += 1;}if (index == position) {return current;}return NULL;}定位对给定表元素的值,找出这个元素的位置遍历链表,若某节点数据域与要查找的元素data相等则返回当前遍历的次数index//求表head中第⼀个值等于x的结点的序号(从1开始),若不存在这种结点,返回结果为0 时间复杂度 :O(n)int locate(LinkList list,int data){int index = 1;Node *c;c = list->next;while (c != NULL){if (c->data == data){return index;}index+=1;c = c->next;}return 0;}插⼊在表的第i个数据元素结点之前插⼊⼀个以x为值的新结点new获取第i的节点的直接前驱节点pre(若存在),使new.next = pre.next;pre.next = new;//在表head的第i个数据元素结点之前插⼊⼀个以x为值的新结点时间复杂度 :O(n)void insert(LinkList list, int position, int data) {Node *pre, *new;if (position == 1) {//若插⼊位置为1 则表⽰要插⼊到表的最前⾯即head的后⾯pre = list;} else {//pre表⽰⽬标位置的前⼀个元素所以-1pre = get(list, position - 1);if (pre == NULL) {printf("error:插⼊的位置超出范围");exit(0);}}new = malloc(sizeof(Node));new->data = data;new->next = pre->next;pre->next = new;list->length += 1;}删除删除给定位置的节点获取⽬标节点target的直接前驱节点pre(若pre与⽬标都有效),pre.next = target.next; free(target);//删除链表中第position个位置的节点时间复杂度 :O(n)void delete(LinkList list,int position){//获取要删除节点的直接前驱Node *pre;if (position == 1){ //如要删除的节点是第⼀个那直接前驱就是头结点pre = list;}else{pre = get(list,position-1);}////如果⽬标和前驱都存在则执⾏删除if (pre != NULL && pre->next != NULL){Node *target = pre->next; //要删除的⽬标节点//直接前驱的next指向⽬标的直接后继的nextpre->next = target->next;free(target);printf("info: %d被删除\n",target->data);list->length -= 1;}else{printf("error:删除的位置不正确!");exit(1);}}创建具备指定数据节点的链表//效率⽐较差算法时间复杂度 :O(n^2)LinkList createLinkList1(){LinkList list = initialLinkList();int a;//输⼊的数据int index = 1; //记录当前位置scanf("%d",&a);while (a != -1){ // O(n)insert(list,index++,a); // O(n^2) 每次都要从头遍历链表scanf("%d",&a);}return list;}//尾插算法记录尾节点从⽽避免遍历时间复杂度 :O(n)LinkList createLinkList2(){LinkList list = initialLinkList();int a;//输⼊的数据Node *tail = list;//当前的尾部节点scanf("%d",&a);while (a != -1){ // O(n)Node * newNode = malloc(sizeof(Node)); //新节点newNode->next = NULL;newNode->data = a;tail->next = newNode;//尾部节点的next指向新节点tail = newNode;//新节点作为尾部节点scanf("%d",&a);}return list;}//头插算法每次插到head的后⾯,不⽤遍历但是顺序与插⼊时相反时间复杂度 :O(n)LinkList createLinkList3(){LinkList list = initialLinkList();int a;//输⼊的数据Node * head = list;scanf("%d",&a);while (a != -1){ // O(n)Node * newNode = malloc(sizeof(Node)); //新节点newNode->next = NULL;newNode->data = a;newNode->next = head->next;//将原本head的next 交给新节点;head->next = newNode;//在把新节点作为head的next;scanf("%d",&a);}return list;}优缺点优点:在⾮终端节点插⼊删除时⽆需移动其他元素⽆需预分配空间,⼤⼩没有限制(内存够的情况)缺点:⽆法随机存取读取数据慢链表与顺序表的对⽐:操作顺序表链表读表元O(1)O(n)定位O(n)O(n)插⼊O(n)O(n)删除O(n)O(n)。
数据结构线性表ppt课件
01
02
03
04
插入操作
在链表的指定位置插入一个新 节点,需要修改相邻节点的指
针。
删除操作
删除链表的指定节点,需要修 改相邻节点的指针。
查找操作
从链表的头节点开始,顺序遍 历链表,直到找到目标元素或
遍历到链表末尾。
遍历操作
从链表的头节点开始,顺序访 问每个节点,直到遍历到链表
末尾。
04 线性表应用举例 与问题分析
多项式表示与计算问题
01
02
03
多项式表示方法
数组表示法和链表表示法 。
数组表示法
将多项式的系数按次序存 放在一个数组中,通过下 标表示对应的幂次。
链表表示法
每个节点包含系数和指数 两个数据域,以及一个指 向下一个节点的指针域。
一元多项式相加算法设计
• 算法思想:将两个多项式中的同类项系数相加,得到新的 多项式。
删除操作
删除指定位置i的元素,需要将i之后的元素都向前移动 一个位置。
03 链式存储结构及 其实现
链式存储结构原理及特点
链式存储结构原理
使用一组任意的存储单元存储线 性表的数据元素(这组存储单元 可以是连续的,也可以是不连续 的)。
链式存储结构特点
逻辑上相邻的元素在物理位置上 不一定相邻,元素之间的逻辑关 系是通过指针链接来表示的。
...,an组成的有序序列。
性质
集合中必存在唯一的一个“第一元素 ”。
集合中必存在唯一的一个“最后元素 ”。
除最后元素之外,均有唯一的后继。
除第一元素之外,均有唯一的前驱。
线性表与数组关系
数组是线性表的一种表现和实现形式。
线性表更侧重于逻辑概念,而数组则是这种逻辑概念在计算机中的一种存储方式。
线性表
n 1
n1 2 2
顺序表中插入操作的平均时间复杂度为O(n)
5. 删除
算法过程
序号 内容
0
1
a1
2
a2
3
a3
…
…
i-1
ai1
i
ai
i+1 ai1
…
…
n
an
n+1
maxsize -1
序号 内容
0
1
a1
2
a2
3
a3
…
…
i-1
ai1
i
ai1
i+1
ai 2
…
…
n-1
an
n
maxsize -1
删除前
删除后
把线性表(a1, a2, a3,......, an )顺序存放在内存中
地址 内存
b
a1
b+L
a2
b+2L
a3
…
…
…
…
b+(i-1)×L ai
… … b+(n -1)×L an
序号 0 1 2 3 … …
i
… … n
maxsize-1 顺序存储结构示意图
第二章 线性表
假设线性表的每个元素需占用L个存储单元,并以所占的 第一个单元的存储地址作为数据元素的存储位置(上图中 为b)。则线性表中第i+1个数据元素的存储位置LOC(ai+1) 和第i个数据元素的存储位置LOC(ai)之间满足下列关系:
第二章 线性表
例2-3、学生健康情况登记表如下:
姓 名 学 号 性 别 年龄 健康情况
王小林 790631 男 18 健康
数据结构之线性表
线性表是最简单、最基本、最常用的数据结构。线性表是线性结构的抽象(Abstract),线性 结构的特点是结构中的数据元素之间存在一对一的线性关系。这种一对一的关系指的是数据 元素之间的位置关系,即:( 1)除第一个位置的数据元素外,其它数据元素位置的前面都 只有一个数据元素;( 2)除最后一个位置的数据元素外,其它数据元素位置的后面都只有 一个元素。也就是说,数据元素是一个接一个的排列。因此,可以把线性表想象为一种数据 元素序列的数据结构。
单链表的存储
链表是用一组任意的存储单元来存储线性表中的数据元素(这组存储单元可以是连续的,也 可以是不连续的)。那么,怎么表示两个数据元素逻辑上的相邻关系呢?即如何表示数据元 素之间的线性关系呢?为此,在存储数据元素时,除了存储数据元素本身的信息外,还要存 储与它相邻的数据元素的存储地址信息。这两部分信息组成该数据元素的存储映像(Image), 称为结点(Node)。把存储据元素本身信息的域叫结点的数据域(Data Domain),把存储与它 相邻的数据元素的存储地址信息的域叫结点的引用域(Reference Domain)。因此,线性表 通过每个结点的引用域形成了一根“链条”,这就是“链表”名称的由来。 如果结点的引用域只存储该结点直接后继结点的存储地址,则该链表叫单链表(Singly Linked List)。把该引用域叫 next。单链表结点的结构如图所示,图中 data 表示结点的数 据域。
data = val; next = p; }
//构造器
public DbNode(DbNode<T> p) {
next = p; }
//构造器 public DbNode(T val) { data = val; next = null; }
数据结构导论 第2章 线性表
线性表是一种线性结构,线性结构的特点是数据元 素之间是一种线性关系,数据元素“一个接一个的 排列”。 线性结构是n(n>=0)个结点的有穷序列。对于 n>0的线性结构表示成: (a1,a2,… ai-1,ai,ai+1,…an) a1称为起始结点 an称为终端结点 起始结点, 终端结点; 起始结点 终端结点 ai-1 称为 ai 的直接前趋 i+1 称为 ai 的直接后继 直接前趋,a 直接后继。 直接前趋 直接后继
4.查找(定位) locate(L,x): .查找(定位) :
依次将顺序表L中的每个元素与给定的值x进行比 较。若找到则返回其序号(下标+1),否则返回0。 int locate (sqlist L, datatype x) { int i; for ( i=0; i<st; i++) if (L.data[i]==x) return (i+1); return(0); }
void insert (sqlist *L, datatype x, int i ) { if (i<1 || i>L->last+1) error (“插入位置错误”); else if (L->last==maxsize) error (“溢出”); else { for (j=L->last-1; j>=i-1; j--) //往后移动元素 //往后移动元素 L->data[j+1]=L->data[j]; L->data[i-1]=x; //插入x L->last++; //修改表长 } }
常见的线性表的基本运算有以下几个: 常见的线性表的基本运算有以下几个:
数据结构第2章线性表A
在线性表的第i个位臵前插入一个元素的示意图如下:
1 2 3 4 插入25 5 12 1
12
13 21
13
21 24 28 30 42 77
2
3 4 5 6 7 8
24
25
6
7 8
28
30 42 77
9
16
3)删除
删除线性表的第i个位臵上的元素
实现步骤: 将第i+1 至第n 位的元素向前移动一个位臵; 表长减1。 注意:事先需要判断,删除位臵i 是否合法? 应当符合条件:1≤i≤n 或 i=[1, n] 核心语句: for ( j=i+1; j<=n; j++ )
18
2.2.3 顺序表的运算效率分析
时间效率分析:
算法时间主要耗费在移动元素的操作上,因此 计算时间复杂度的基本操作(最深层语句频度) T(n)= O (移动元素次数) 而移动元素的个数取决于插入或删除元素的位臵.
讨论1:若在长度为 n 的线性表的第 i 位前 插入一个元素, 则向后移动元素的次数f(n)为: f(n) = n – i + 1
例2 分析学生情况登记表是什么结构。
学号 姓名 性别 年龄 班级
0406010402
0406010405 0406010406 0406010410 0406010413 :
陈杰
邓博 管杰 黄腾达 李荣智 : : :
2004级计软04-1班
2004级计软04-1班 2004级计软04-1班 2004级计软04-1班 2004级计软04-1班 :
InitList( &L ); DestoryList( &L ); //建空表,初始化 //撤销表,释放内存
线性结构的特点在数据元素的非空有限集中存在唯
前驱 (4)除最后一个之外,集合中的每个数据元素均只有一
个后继
2.1 线性表的概念
“线性表”简称为表,是零个或多个元素的有穷序列,通 常可以表示成k0,k1, …,kn-1 (n≥1)。表中所含元 素的个数称为表的“长度”。长度为零的表称为“空表”。 表中的元素又称“表目”。
由上面的基本运算还可以构成其它较为复杂的运算, 如创建线性表。
#include <stdio.h> #include <alloc.h>
/* 符号常量 */ #define MAXNUM #define FALSE #define TRUE #define SPECIAL
#define PI
100 /* 线性表空间大小 */
palist ->n = 0; else
printf("Out of space!!\n"); return palist; };
算法2.9 判断线性表是否为空 int isNullList_seq( PSeqList palist ) {
return( palist->n == 0 ); }
说明:上述算法在具体上机实现时,要将下面的类型说明、
*/ { if (( p>=0 )&&( p<palist->n - 1 ))
return ( p + 1 ); else
return ( -1 ); } 算法2.7 求前一个元素的下标位置 int previous_seq( PSeqList palist, int p ) /* 求palist所指顺序表中下标为p的元素的前驱元素的下标位置
计算机图形学-图形数据结构
(2)插入操作 顺序表的删除操作是指在长度为 n 的线性表的第 i-1个元素 和第 i 元素之间插入一个新的元素,就是要使长度为 n 的线性表
T =(t1,…,ti–1,ti,…,tn) 变成长度为 n +1 的线性表
(t1,…,ti–1,x,ti,…,tn)
2023/6/18
12
计算机图形学
数据元素 ti–1和 ti 之间的逻辑关系发生改变。为了在存储结 构上反映这个变化,除非 i = n +1,否则必须移动元素才能反映 这个逻辑关系的变化。具体的算法步骤如下:
t[1] t[2] … t[i-1] t[i] t[i+1] … t[n]
X
(3)顺序表的应用及不足
在图形程序中,可用顺序表对简单的图形(包括二维和三
维)进行建模:
顶点表(各顶点坐标)
边表(各顶点间的连边规则)
2023/6/18
14ห้องสมุดไป่ตู้
计算机图形学
但由于图形间的运算,使得两表不断改变,致使表中元素搬家 频繁。因此,线性表适用作静态表。图形间的运算,使得图形 的几何关系和拓扑关系经常发生变化(见图例)。
① 用一组地址连续的存储单元依次存储线性表的数据 元素,采用这种存储结构的线性表称为顺序表;
② 用一组任意的存储单元存储线性表的数据元素,采 用这种存储结构的线性表称为链表; 线性表的操作。线性表的基本操作有存取元素、删除和 插入元素操作等。
2023/6/18
8
计算机图形学
2.2 线性表的顺序表示和实现
2023/6/18
30
计算机图形学
3.2 二叉树
二叉树是最为重要的树形结构,与一般形态的树的区别在 于:
第3章线性表概要
链式存储的几种形式
单链表 循环链表 双向链表
单链表的定义
typedef int DataType; class Item { public: DataType data; Item * next; Item(){next=NULL;} };
class Link { public: Item *head; Link(){head=NULL;} ~Link(){DeleteAll();} void Initiate(); void DeleteAll(); void HeadCreate(int n); void TailCreate(int n); void HeadCreateWithHead(int n); void TailCreateWithHead(int n); int Length(); Item *Locatex(DataType x); Item *Locatei(int i); DataType Get(int i); bool Insert(DataType x,int i); bool Deleted(int i); void Print(); };
Ein P i (n i 1)
i 1
n 1
在等概率情况下,Pi=1/(n+1),则
1 n1 n Ein P (n i 1) i (n i 1) n 1 i 1 2 i 1
n 1
时间复杂度为O(n)
典型操作的算法实现
3. 删除运算
线性表的删除运算是指将表中第i个元素从线性表中删除, 使原表长为n的线性表(a1,a2,…,ai-1,ai,ai+1,…, an)变成表长为n-1的线性表 (a1,a2,…,ai-1,ai+1,…,an) i的取值范围为1≤i≤n。
数据结构 第二章__线性表(本)
数据结构与算法华东师范大学计算机系杨沛第二章线性表2.1 线性表的基本概念线性表是具有相同数据类型的数据元素的有限序列。
由n(n≥0)个数据元素k0,k1,…,kn-1组成的线性表记为(k0 ,k1 ,…,kn-1),线性表中包含的数据元素的个数n称为线性表的长度(length),称长度为零的线性表为空的线性表(简称为空表)。
相关概念:表头、表尾、前驱、后继有序线性表:数据元素的相对位置与它们的值有联系。
无序线性表:数据元素的相对位置与它们的值没有联系。
第二章线性表例小于20的质数组成的线性表(2,3,5,7,11,13, 17,19);英文字母表也是线性表,表中每个字母是一个数据元素:(A,B,C,……,Z);2.2 顺序表2.2.1 线性表顺序表(sequential list)就是顺序存贮的线性表,即用一组连续的存贮单元依次、连续地存贮线性表中的结点。
如果每个结点占用s个存贮单元,并假设存放结点ki(0≤i≤n-1)的开始地址为loc(k0),则结点ki的地址loc(ki)可表示成Loc(ki) =loc(k0) + i*s。
2.2 顺序表在C 语言中,可用数组表示线性表:#define MAXN 100int list[MAXN];int n;线性表的结点k 0,k 1,…,k n-1依次存放在数组单元list[0],list[1],…,list[n-1]。
2.2.1 线性表最大表长实际表长线性表2.2 顺序表2.2.1 线性表假设s=sizeof(int),则可得到计算ki的地址的公式,因loc(ki)=&list[i],而&list[i]=&list[0]+i·s,故loc(ki)=&list[0]+i·s。
2.2 顺序表2.2.2 顺序表的操作(1)初始化:初始长度置为0即可(n=0;),数组空间在编译时分配。
(2)顺序表的插入:插入算法的C函数SqListInsert():若插入位置i不在可以插入的位置上,即i<0或i>n,则返回0;若n=MAXN,即线性表已满,此时数组list[]没有多余的存贮单元可以存放新结点,则返回-1;若插入成功,则返回12.2 顺序表实际表长(2)顺序表的插入:int SqListInsert(int list[],int*p_n,int i,int x) {int j;if(i<0||i>*p_n)return(0);//i不是合法的插入位置if(*p_len==MAXN)return(-1);//线性表已满2.2 顺序表for(j=*p_n;j>i;j--)list[j]=list[j-1];//结点右移list[i]=x;(*p_n)++;//表长加1return(1);}2.2 顺序表(2)顺序表的插入:对于存放在数组list[]中的、具有n个结点的顺序表,为了把值为x的结点插在表的位置i(0≤i≤n)上,可调用如下的语句:k=SqListInsert(list, &n, i, x);注:结点移动是本算法的关键操作2.2 顺序表(3)顺序表的删除:删除算法的C函数SqListDelete():在具有n个结点的顺序表中,删除第i(0≤i≤n-1)个位置上的结点,使线性表长度减1,若删除位置不合法,即i<0或i≥n,则返回0;若删除位置合法,即0≤i≤n-1,则删除成功,返回1。
数据结构课件之线性表(ppt 86页)
删除算法
int DelList(SeqList *L,int i,ElemType *e)
/*在顺序表L中删除第i个数据元素,并用指针参数e返回其值*/
{ int k;
if((i<1)||(i>L->last+1))
{ printf(“删除位置不合法!”); return(ERROR); }
*e= L->elem[i-1]; /* 将删除的元素存放到e所指向的变量中*/
loc(ai) =loc(a1)+(i-1)×k
8
15.10.2019
顺序存储结构示意图
存储地址
Loc(a1) Loc(a1)+(2-1)k
…
loc(a1)+(i-1)k
…
loc(a1)+(n-1)k
...
loc(a1)+(maxlen-1)k
内存空间状态
a1 a2
…
ai
…
an
9
逻辑地址
1 2
…
i
操作前提:L为未初始化线性表。 操作结果:将L初始化为空表。 操作前提:线性表L已存在。 操作结果:将L销毁。 操作前提:线性表L已存在 。 操作结果:将表L置为空表。
………
}ADT LinearList
6
15.10.2019
2.2 线性表的顺序存储
2.2.1 线性表的顺序存储结构 2.2.2 线性表顺序存储结构上的基本运算
17
15.10.2019
删除算法示意
将线性表(4,9,15,21,28,30,30,42,51,62)中的第5个元素 删除。
序号
1 2 3 4 5 6 7 8 9 10 4 9 15 21 28 30 30 42 51 62
第12章-线性表
第12章线性表数据结构: 是相互之间存在一种或多种特定关系的数据元素的集合。
在任何问题中, 数据元素都不是独立存在的, 而是在它们之间存在着某种关系, 这种数据元素相互之间的关系称为结构。
通常有4种结构:(1)集合:结构中的数据元素之间除了“同属于一个集合”的关系外, 别无其它的关系;一个大学同学之间的关系就是“集合”;(2)线性结构: 结构中的数据元素之间存在着一个对一个的关系;一个班级同学之间的学号有先后关系(一对一的关系);(3)树形结构: 结构中的数据元素之间存在一个对多个的关系;一个班主任对该班上的学生之间的关系;(4)图状结构或网状结构: 结构中的数据元素之间存在多个对多个的关系;一个班上的同学之间的关系。
线性结构的特点是:在数据元素的非空有限集中, 存在着以下:(1)存在唯一的一个被称做“第一个”的数据元素(2)存在唯一的一个被称做“最后一个”的数据元素(3)除第一个之外, 集合中的每个数据元素均只有一个前驱(4)除最后一个之外, 集合中的每个数据元素均只有一个后继满足这种关系的数据集合就是“线性表”。
12.1 线性表的定义线性表(Linear List)是最常用且最简单的一种数据结构。
简言之, 一个线性表是n个数据元素的有限序列。
每个数据元素的具体含义可以不同。
在稍复杂的线性表中, 一个数据元素可以由若干个数据项组成(如一个结构体就是一个数据元素, 而结构中的每个成员就是一个数据项)。
在这种情况下, 常把数据元素称为记录, 含有大量记录的线性表又称为文件。
线性表可以有两种实现方式: 顺序方式、链式方式。
顺序方式实现的称为“顺序表”, 链式方式实现的称为“链表”。
12.2 线性表的顺序表示和实现一般表示顺序表的结构为:#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量#define LISTINCREMENT 10 //线性表存储空间的分配增量typedef int ElemType; //使用typedef定义一种新类型ElemType, 此处它其实就是inttypedef struct{ElemType *elem; //存储空间基址int length; //当前长度int listsize; //当前分配的存储空间(个)}SqList;需要实现的操作有:(1)初始化(2)销毁(3)清空(4)判空(5)求长度(6)获取第i个元素(7)对第i个元素设值(8)在第i个位置上插入一个元素(9)删除第i个元素(10)求某个元素的前驱(11)求某个元素的后继(12)查找某个指定值的元素的位置(13)遍历实现如下:1.初始化/*函数: 初始化一个线性表*/Status InitList_Sq(SqList &L){L.elem=(ElemType*)malloc(sizeof(SqList)*LIST_INIT_SIZE);if(L.elem==NULL) //申请空间失败, 程序直接退出exit(OVERFLOW);L.length=0;L.listsize=LIST_INIT_SIZE;return OK;}其中exit(代码)是直接退出程序。
2.2 线性表及其顺序存储结构
一般情况下,要删除第i (1≤i≤n )个 元素,需要从第i+1 个元素开始,直到第n 个元素之间,共有n-i 个元素依次向前移动 了一个位置。删除结束后,顺序表的长度就 缩小了1。在平均情况下,要在顺序表中删 除一个元素,需要移动表中一半的元素。
在顺序表L中删除第i个元素并用x 返回其 值的算法DeleteList描述如下:
void DeleteList(SeqList *L,int i, ElemType *x) {
int j,n=L->length; if(i<1||i>n) {
printf(" \n i值不合法!"); exit(1); }
在顺序表中删除一个元素,平均约移动表 中一半的元素。平均时间复杂度为O(n)。最 好的情况是当i=n,即在表尾删除时,不需要 移动元素;最坏的情况是当i=1,即在表头删 除时,需要移动表中n-1个元素。
栈和队列是两种特殊的线性表,它们的逻 辑结构和线性表相同,只是运算规则较线 性表有更多的限制 。
在表中插入一个元素,平均要移动一半的元 素,平均时间复杂度为O(n)。最好的情况是
在表尾插入时,不需要移动元素;最坏的情况 是在表头插入时,需要移动表中n个元素。
假设,在长度为n的顺序表的任意位置i (1≤i≤n)删除该位置元素的概率为qi=1/n, 所需移动元素的次数为n-i,那么,每删除一 个元素,所需移动元素的次数的平均值为: Ade = (n-1)/2
ElemType GetElem(SeqList *L,int i) {/*取表中第i个数据元素*/