一、线性结构定义
本质特征:(结点间逻辑关系是一对一)
- 只有一个首结点和尾结点
- 除了首位结点外,其他结点只有一个直接前驱和一个直接后
线性表包括:线性表、堆栈、队列、字符串、数组等
二、线性表的抽象数据类型(List)
链表基本运算:修改、插入、删除、查找、排序
-
1.修改:通过数组的下标便可访问某个特定元素并修改之
核心语句:Vlil=x(时间效率是O(1)。)
- 2.插入:在线性表的第i个位置前插入一个元素
核心语句:
for (j=n; j>=i; j--)
a[j+1]=a[ j ]; //插入位置后面的元素全部后移
a[i]=x; //插入x
n++; //表长+1
时间复杂度:O(n) 等概率情况下,需要平均移动一半元素(n/2)
空间复杂度:O(1)
- 3.删除:删除线性表的第i个位置上的元素
核心语句:
for (j=n; j>=i; j--)
a[j-1]=a[ j ]; //删除后的元素全部前移
n--; //表长-1
C语言操作表示:
ADT List {
数据对象:D = {ai | ai ∈ ElemSet,i = 1, 2, ```, n, n ≥ 0 }
数据关系:R1 = { < a i-1,ai > | ai-1,ai ∈ D,i = 2, ```, n }
基本操作:
InitList(&L); //建空表,初始化
DestoryList(&L); //撤销表,释放内存
intLengthList(L); //求表中元素个数,即表长
PosITIoNLocateElem(LElemTypee,compare()) //查找e
PriorElem(Lcure,&pree); //求当前元素e的前驱
NextElem(L,cur_e,next_e); //求当前元素e的后继
ListInsertBefore(&L,i,e) //把e插入到第i个元素之前
ListDelete(&L,i,&e); //删除第i个元素井“看”此元素
ListTraverse(L,Visit()); //"看”表中全部元素(遍历)
} ADT List
//参数中没有&符号,一定是输入!!
//有&符号,一定是输出(有更改)!该参数是不是输入需要具体分析
二、顺序表(SqList)
定义:线性表的顺序表示又称为顺序存储结构或顺序映像;把逻辑上相邻的数据元素存储在物
理上相邻的存储单元中的存储结构(即逻辑上相邻的元素,物理上也相邻)
存储方法:用一组地址连续的存储单元依次存储线性表的元素。
存储特点:
- 逻辑上相邻的数据元素,其物理上也相邻
- 若已知表中首元素在存储器中的位置,则其他元素存放位置亦可求出(利用数组V[n]的下标)(下标起点为0时:LOC(a)=LOC(a)+L*(i) 提取元素速度快)
空间分配方法:
- 静态分配:在编译时即可确定数组的大小,数组的大小在声明时就已经确定了。
int *arr;
arr = (int *)malloc(size * sizeof(int)); // 动态分配一个包含size个整数的数组
- 动态分配——先为顺序表空间设定一个初始分配量,一旦因插入元素而空间不足时,可为顺序表增加一个固定长度的空间增量。(动态分配的数组需要在使用完毕后通过调用free()函数释放内存,以避免内存泄漏问题)
int *arr;
arr = (int *)malloc(size * sizeof(int)); // 动态分配一个包含size个整数的数组
arr_new = int *newArr = (int *)realloc(arr, newSize * sizeof(int));
//新开辟一大小为newsize的连续空间,并把以*arr为首址的原空间数据都拷见进去
///C语言表示
sizeof(x) //计算变量×的长度(字节数);
malloc(m) //开辟m字节长度的地址空间,并返回这段空间的首地址;
realloc(*p,newsize) //函数的意思是:新开一片大小为newsize的连续空间,并把以*p为首址的原空间数据都拷贝进去。
free(p) //释放指针p所指变量的存储空间,即彻底删除一个变量。
//大量的malloc和free会把内存分成很多碎块,不建议无限制的使用(用堆来解决)
三、动态链表(LinkList)
存储方法:为指针新开辟一处空间
存储特点:其结点在存储器中的位置是随意的,即逻辑上相邻的数据元素在物理上不一定相邻。(方便删除插入——空间换时间)
生成表示:(分配空间不连续+尾结点必须是NULL否则停不了)
void build()
{
int i;
head=(node *)malloc(m); //m=sizeof(node)前面已求出
p=head;
for( i=1; i<26; i++) //因尾结点要特殊处理故计26
{ p->data=i+'a'-l; //第一个结点值为字符a
p->next=(node*)malloc(m): //为后继结点“挖坑”!
p=p->next;} //让指针变量P指向后一个结点
p->data=i+'a'-1; //最后一个元素要单独处理
p->next=NULL; //单链表尾结点的指针域要置空!!!!!
}
四、静态链表(SLinkList)
定义:定义一个结构型数组(每个元素都含有数据域和指示域),就可以完全描述链表,指示域就相当于动态链表中的指针,称为游标。(结合链表和顺序表的优点)
#define MAXSIZE 1000 //预分配最大的元素个数(连续空间)
typedef struct
{
ElemType data; //数据域
int cur; //指示域(指向后继)
}component,SLinkListr[MAxsizE]; //这是一维结构型数组
插入:
Step1:将QIAN的游标值存入LIU的游标中:
S[7].cur = s[3].cur ;
Step2:将QIAN的游标换为新元素LIU的下标:
s[3].cur = 7