(以下内容都是自己上课的总结分析,有不对的欢迎提出)
分析
从“线性结构”几个字来分析:线性,就是指像一条线一样的一种结构,并且有头有尾,有有限个结点,每个结点前面最多紧挨着一个(叫直接前驱)后面也最多只紧挨着一个(直接后驱)。
线性结构的类型
1.线性表:就好像我们成绩单一样
2.堆栈:这个就是说对于这个线性结构,只能从一个口进出
3.队列:就好像水龙头一样,只能顺着走,不能到着流,和排队打饭也一样,先去的先结账,后去的只能等前面的结束了才轮到。
4.还有字符串、数组等
线性表
1.就像学生表一样,同一个线性表一定有相同的特性,元素与元素之间的关系也是线性的一种关系。
案例:比如一元多项式相加(多项式就是按照指数从底到高排列的),如下图,将系数与未知数的指数匹配起来
将前两个多项式想象成为两个数组A和B,然后创建一个新的数组C,对于A和B,分别从头开始遍历,然后每次都进行比较,
如果说指数相同,那就让系数相加,如果和不等于0,就在C中把相加后的添加进去,
如果指数不相同,就让小的直接复制到数组C里面去。当某一个多项式遍历完以后,直接将另一个剩下的多项式复制即可。
这里,如果我们用顺序存储结构,就是说这个数组按照顺序排列的,如果有系数为0也需要占用一个位置,这样真的很不方便。
这里我们就要想到链式存储结构,其实就是指在线性表中你可以随便排,只需要设计一个指针,指向它即可。后面再做解释。
线性表的顺序表示和实现1.定义:就是说这个线性表,其储存的内容有一点的顺序,储存内容的地址也有一定的顺序,这妞是顺序存储结构或者叫顺序映像,就是像数组一样。
顺序表类型的定义:define:是下定义的意思,定义一个数组,且其最大的长度是100
typedef:type:类型,def(define) ,struct:结构。意思是:定义一个结构类型
SqList:list:列表,SqList意思是顺序链表,
补充:我们会看见用C语言动态分配函数的情况(
1.malloc(m):开辟m字节长度的地址空间,并且可以返回这段空间的首地址。
2.sizeof(x):计算变量X的长度。
3.free(p):释放指针p所指的存储空间,意思是删除不要的一个变量。
int *p1 = new int;或者:int *p1 = new int (10);
delete 指针p,delete p1,像这样。这个释放的是指针P所指的内存,p必须是new操作的返回值。
理解:ststus:状态
Status InitList_Sq(SqList &L){ //构造一个空的顺序表L
L.elem=new ElemType[MAXSIZE]; //为顺序表分配空间
if(!L.elem) exit(OVERFLOW); //存储分配失败
L.length=0; //空表长度为0
return OK;
}
参数用指针:
Status InitList_Sq(SqList *L){ //构造一个空的顺序表L
L-> elem=new ElemType[MAXSIZE]; //为顺序表分配空间
if(! L-> elem) exit(OVERFLOW); //存储分配失败
L-> length=0; //空表长度为0
return OK;
}
销毁线性表、清空线性表、求线性表的长度、判断是否为空
//销毁线性表L
void DestroyList(SqList &L)
{
if (L.elem) delete[]L.elem; //释放存储空间
}
//清空线性表L
void ClearList(SqList &L)
{
L.length=0; //将线性表的长度置为0
}
//求线性表L的长度
int GetLength(SqList L)
{
return (L.length);
}
//判断线性表L是否为空
int IsEmpty(SqList L)
{
if (L.length==0) return 1;
else return 0;
}
取值(根据位置i获取相应位置数据元素的内容)
获取线性中的某个元素,首先要判断这个元素是否在这个顺序表里面,如果不在就要返回error
否则的话,所要取得元素就是i-1个位置,也就是存储单元里面,为什么要减一,因为数组是从0开始的对吧。
int GetElem(SqList L,int i,ElemType &e)
{
if (i<1||i>L.length) return ERROR;
//判断i值是否合理,若不合理,返回ERROR
e=L.elem[i-1]; //第i-1的单元存储着第i个数据
return OK;
}
查找(根据指定数据获取数据所在的位置)
在一个线性表里面寻找我们需要的元素,既然是查找,对于顺序结构就只能一个一个位置寻找,(这里就可以想一下:如果元素就是第一个位置,如果元素在最后一个位置,或者说元素直接不存在,这里面就牵涉到时间复杂度和优化程序的问题,我也还不太清楚)
int LocateELem(SqList L,ElemType e)
{
for (i=0;i< L.length;i++)
if (L.elem[i]==e) return i+1;
return 0;
}
插入(插在第 i 个结点之前)
插入在第i个结点之前,意思就是说插入以后,原本的第i个位置就变成了我们所插入的元素,然后后面的元素就需要依次往后面移动。(这里很明显想到,如果插入的位置就在第一个位置,那么就需要把所有的后往后移动,这个很明显不明智)
而且插入元素前我们要判断:插入的位置是否合理、这个顺序表还能插入吗,是不是已经满了、需要先把第i以后的元素往后移动,空出第i的位置、然后就可以把需要插入的元素放进去了、最后还需要把表长加一,插入成功后返回return OK;
时间算法分析:n/2
//在线性表L中第i个数据元素之前插入数据元素e
Status ListInsert_Sq(SqList &L,int i ,ElemType e){
if(i<1 || i>L.length+1) return ERROR; //i值不合法
if(L.length==MAXSIZE) return ERROR; //当前存储空间已满
for(j=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j]; //插入位置及之后的元素后移
L.elem[i-1]=e; //将新元素e放入第i个位置
++L.length; //表长增1
return OK;
}
删除
大概思路如下图:也需要先判断删除的位置是否合法----->将要删除的元素保存在e中---->将第i后的i+1到n位置的元素依次向前移动一个位------>最后表长需要减一,删除成功后返回OK。
时间复杂度;(n-1)/2
//将线性表L中第i个数据元素删除
Status ListDelete_Sq(SqList &L,int i){
if((i<1)||(i>L.length)) return ERROR; //i值不合法
for (j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j]; //被删除元素之后的元素前移
--L.length; //表长减1
return OK;
}
顺序表(顺序存储结构)的特点
逻辑结构与存储结构一致
可以认为访问每个元素所花费的时间相等。、
这种存储方式也叫随机存取法(也就是说可以想删除哪里,或者把元素添加在哪里,只需要指定相应的位置即可,只是是在插入和删除时的工作量会有点大(引入链表))
链式存储结构(链式表示也叫非顺序映像或者链式映像)储存的位置是任意的,逻辑上相邻的数据元素在物理上不一定相邻。
①为操作方便,总是在链表的第一个结点之前附设一个头结点(头指针)head指向第一个结点。
头结点的数据域:可不存储任何信息(也可存储链表长度等信息)。
单链表(最后一个结点的指针指向头结点)和双链表(将头结点和尾结点链接起来)都可以构成循环链表,称为单&双[向]循环链表。
循环结构:
顺序存储结构中,很容易实现线性表的一些操作:初始化、赋值、查找、修改、插入、删除、求长度等。
1.初始化:都是要让表的长度为0
2.



