线性表的类型定义
线性结构的定义:若结构是非空有限集,则有且仅有一个开始结点和一个终端结点,并且所有结点都最多只有一个直接前趋和一个直接后继。
线性结构表达式:(a1 , a2 , ……, an):(a1 , a2 , ……, an) ,是一个有序(次序)集 。
线性结构的特点:① 只有一个首结点和尾结点; ② 除首尾结点外,其他结点只有一个直接前驱和一个直接后继。
简言之,线性结构反映结点间的逻辑关系是 一对一 的。
线性结构包括线性表、堆栈、队列、字符串、数组等等,其中,最典型、最常用的是------线性表
线性表的定义:用数据元素的有限序列表示
n=0时称为空表,记作L=( )
线性表的类型定义
说明: ⑴ 线性表的基本操作根据实际应用而定; ⑵ 复杂的操作可以通过基本操作的组合来实现; ⑶ 对不同的应用,操作的接口可能不同。
例:假设有两个集合 A 和 B 分别用两个线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合A=A∪B。
即:需对线性表作如下操作: 扩大线性表 LA,将存在于线性表LB 中而不存在于线性表 LA 中的数据元素插入到线性表 LA 中去。
1.取得线性表 LB 中一个数据元素;GetElem(Lb, i, e);
2.依次在线性表 LA 中进行查访; LocateElem(LA, e, equal( ));
3.若不存在,则插入之。 ListInsert(LA, n+1, e); ( n 表示线性表 LA 当前长度)
void union(List &La, List Lb) {
La_len = ListLength(La); // 求线性表La的长度
Lb_len = ListLength(Lb); // 求线性表Lb的长度
for(i=1;i<=Lb_len; i++) {
GetElem(Lb, i, e); // 取Lb中第i个数据元素赋给e
if (!LocateElem ( La, e, equal( )) )
ListInsert(La, ++La_len, e);
// La中不存在和 e 相同的数据元素,则插入之
}//for
} // union
例:已知线性表LA和LB中的数据元素按值非递减有序排列,现要求将LA和LB归并为一个新的线性表LC,且LC中的数据元素仍按值非递减有序排序。
即:需对线性表作如下操作: LC中的数据元素或是LA中的数据元素,或是LB中的数据元素,则只要先设LC为空表,然后将LA或LB中的元素逐个插入到LC中即可。
1.设置两个指针i,j分别指向LA和LB中数据元素;GetElem(LA, i, ai); GetElem(LB, j, bj);
2.将较小的数据元素插入到LC中; ListInsert(LC, ++k, e);
3.把LA或LB中剩余元素插入LC。
线性表的顺序表示和实现
顺序表的表示
线性表的顺序表示又称为顺序存储结构或顺序映像。
顺序存储定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构。简言之,逻辑上相邻,物理上也相邻。
顺序存储方法:用一组地址连续的存储单元依次存储线性表的元素,可通过数组V[n]来实现。
线性表顺序存储特点:
1. 逻辑上相邻的数据元素,其物理上也相邻;
2. 若已知表中首元素在存储器中的位置,则其他元素存放位置亦可求出(利用数组下标)。计算方法是(参见存储结构示意图):
注意:C语言中的数组的下标从0开始, 即:V[n]的有效范围是V[0]~V[n-1]
线性表的顺序存储结构示意图
“顺序表是一种随机存取的存储结构”,含义为:在顺序表这种存储结构上进行查找操作,其时间性能是O(1)。
计算机内存的存取是如果知道该内存单元的地址,马上就可以读取到里面的内容,速度非常快,称为随机存取。
存储结构和存取结构是两种不同的概念:
存储结构是数据及其逻辑结构在计算机中的表示。
存取结构是在某种数据结构上对查找操作时间性能的描述。如:随机存取,顺序存取
顺序表的实现(或操作)
线性表的动态分配顺序存储结构
线性表的初始化操作
线性表的销毁操作
数据结构基本运算操作有:修改、插入、删除、查找、排序
1) 修改 通过数组的下标便可访问某个特定元素并修改之。核心语句:V[i]=x;显然,顺序表修改操作的时间效率是T(n)=O(1)
status modify(SqList &L, int i, ElemType e){
if (i<1 || i>L.length) //判断位置i是否合法
return ERROR;
L.elem[i-1]=e; //或者 *(L.elem+i-1)=e
return OK;
}
int i;
i=2;
int *p;
p=&i;
cout<<*p<<"\n";
*p=3;
cout<<i;
2)插入 在线性表的第i个位置前插入一个元素
实现步骤:(n为表长)
1)判断插入位置i 是否合法?表是否已满?
2)将第n至第i 位的元素依次向后移动一个位置;
3)将要插入的元素写到第i个位置;
4)表长加1
Status ListInsert_Sq(SqList &L,int i, ElemType e)
3)删除 删除线性表的第i个位置上的元素
实现步骤:(n为表长)
1)判断删除位置i 是否合法
2)将第i+1 至第n 位的元素向前移动一个位置;
3)表长减1
Status ListDelete_Sq(SqList &L,int i, ElemType &e){
If((i<1) ||(i>L.length)) return ERROR
已知两个顺序线性表La和Lb的元素按值非递减排列,归并La和Lb得到新的顺序线性表Lc也按值非递减排列。
void MergeList_Sq(SqList La,Sqlist Lb,Sqlist &Lc)
重点设计几个指针 Pa ,Pb ,Pc ,Pa_last Pb_last
注意三个循环的循环条件
编程实现如下任务:建立一个线性表,首先依次输入数据元素如5,1,4, 2, 9,3, 6,7,8, 10,然后删除第五个元素,再把数据12插入到第六个元素之前,最后依次显示当前线性表中的数据元素。要求用顺序表实现。
Void MergeList_Sq(SqList La, SqList Lb, SqList &Lc){
pa=La.elem;
pb=Lb.elem;
Lc.listsize=Lc.length=La.length+Lb.length;
Pc=Lc.elem= =(ElemType *)malloc(Lc.listsize*sizeof(ElemType));
if(!Lc.elem)exit(OVERFLOW);
pa_last=La.elem+La.length-1;
pa_last=Lb.elem+Lb.length-1;
While(pa<pa_last && pb<pb_last){
if (*pa<=*pb)
*pc++=*pa++;
else
*pc++=*pb++;
}
While(pa<pa_last){
*pc++=*pa++;
}
While(pb<pb_last){
*pc++=*pb++;
}
}
顺序表的运算效率分析
时间效率分析:算法时间主要耗费在移动元素的操作上,因此 计算时间复杂度的基本操作(最深层语句频度) T(n)= O (移动元素次数) 移动元素的个数取决于插入或删除元素的位置.
若在长度为 n 的线性表的第 i 位前 插入一元素,则向后移动元素的次数f(n)为: f(n) =n-i+1 (i取1 to n+1)
若在长度为n的线性表上删除第i位元素,向前移动元素的次数f(n)为: f(n) =n-i (i取1 to n)
假定在表中任意位置插入、删除元素都是等概率的, 插入概率p(i)=1/(n+1) ,删除概率q(i)=1/n ,则:
插入操作时间效率(平均移动次数)
删除操作时间效率(平均移动次数)
因此,时间复杂度T(n)=O(n) 显然,顺序表的空间复杂度S(n)=O(1)
顺序表(线性表的顺序存储结构)的特点:
逻辑关系上相邻的两个元素在物理存储位置上也相邻;
优点:可以随机存取表中任一元素;
缺点:在插入、删除某一元素时,需要移动大量元素。
代码实现:顺序表的基本操作https://blog.csdn.net/qq1457346557/article/details/107122736