前言:以下内容为个人理解和笔记,如有错误之处,还请指正。感谢!
顺序表
定义
1、把线性表的结点,按逻辑顺序依次存放在一组地址连续的存储单元里(一大块连续的存储空间)。
2、如果顺序表的首地址为L0,其中每个元素占m
个字节,那么第i
个元素的存储地址为 L0+ (i-1)*m。
特点
1、元素结点在逻辑上相邻,在物理存储上也相邻。
2、通过位置(下标)可以实现“随机存取”(直接存、取第i
个元素,时间复杂度为O(1)
)。
代码
结构体定义
代码:
#define MAXSIZE 100
typedef int ElemType;
typedef struct {
ElemType *elem; //定义为指针,用new创建时,即表示存储空间的首地址
int length; //顺序表当前长度
}SqList; //定义顺序表的别名
1、个人理解为此处做了两件事,一是定义了一个结构体,而是给这个结构体起了一个别名为SqList
。
初始化
代码:
//C语言实现
bool InitList(SqList *L){
L->elem = (ElemType*)malloc(MAXSIZE*sizeof(ElemType));
//开辟100*4=400个存储单元(字节)
if(!L->elem){
//exit函数的参数为0,表示正常执行程序并退出程序。不为0表示异常退出。
exit(0);
}
L->length = 0;
return true;
}
个人理解,malloc函数前的(ElemType*)
的意思是转化为ElemType
类型的指针,因为“C语言中malloc
返回一个指向已分配空间的 void
指针,若要返回指向非 void
类型的指针,请在返回值上使用类型转换。”来自c语言中malloc的返回值
代码:
//C++实现
bool InitList(SqList *L){
L->elem = new ElemType[MAXSIZE];
if(!L->elem){
exit(0);
}
L->length = 0;
return true;
}
插入
代码:
void InsertList(SqList &L,int i,ElemType e){
//i为逻辑插入位置
if(i < 1 || i > L.length+1){
printf("Position error!");
return ;
}
if(L.length == L.ListSize){
cout << "overflow";
//EXIT_FAILURE值为1,exit(1)表示非正常执行导致退出程序。
exit(EXIT_FAILURE);
}
for(int j = L.length - 1; j >= i - 1; j--){
L.elem[j+1] = L.elem[j];
}
L.elem[i-1] = e;
L.length++;
return;
}
1、逻辑插入位置,不能小于1
(物理为不能小于0
)、不能大于length+1
(物理为不能大于最后一个元素后面的位置,因为中间不能空一格)。
2、插入时,下标问题。要想在逻辑位置为i
(物理位置为i-1
) 的地方插入元素,就必须将物理上第i-1
个元素(及其后面的每个元素)往后移,因此,必须从后往前挨个往后移动,挪出一个位置来插入元素。
第一种情况:
j
从L.length-1
开始,即L. elem[j]
为最后一个元素。j
往前移动,使得每个元素往后移动的话,就得是L.elem[j+1] = L.elem[j]
。要想将第i-1
个元素移动的话,j
就得等于 i-1
,这样才能将第 i-1
个位置上的元素往后移动一格。
即:
for(int j = L.length-1; j >= i-1; i--)
L.elem[j+1] = L.elem[j];
第二种情况:
j
从L.length
开始,即L.elem[j-1]
为最后一个元素。j
往前移动,使每个元素往后移动,则是L.elem[j] = L.elem[j-1]
。要想将第i-1
个元素往后移动的话,那么j
就得等于i
,这样才能将第i-1
个位置上的元素往后移动一格。
即:
for(int j = L.length; j >= i; j--)
L.elem[j] = L.elem[j-1];
删除
代码:
void DeleteList(SqList &L,int i,ElemType &e){
if(i < 1 || i > L.length){
printf("Position error!");
return ;
}
if(L.length == 0){
cout << "error!No elements!";
exit(1);
}
e = L.elem[i-1];
//j从i-1(要删除的那个数)开始,将j+1中的元素向前(j)移一格,j+1最多只能为L.length-1(若j=L.length-1,j+1=L.length,那就越界了),所以是j<L.length-2(很别扭,不要用)
//应该j从i(要删除的数的后面的数)开始,将j中的元素向前(j-1)移一格,则j最多只能为L.length-1,所以应该是j<L.length
for(int j = i; j < L.length-1; j++){
L.elem[j-1] = L.elem[j];
}
L.length--;
return;
}
1、逻辑位置不能小于1
(物理位置不能小于0
)、不能大于L.length
(最多只能删除最后一个元素)。
2、要求将第i
个(物理位置为i-1
)元素删除,并用变量记录该值。删除物理上第i-1
个元素,可以直接将第i
个位置上的元素前移,将其覆盖,其后所有元素都依次(从前往后的顺序)前移,顺序表的长度再-1
,即表示删除了第i-1
个元素。
第一种情况:
j
从i
开始,即L.elem[j-1]
才是要删除的元素,要想将其删除并将其后所有元素前移,则应该是L.elem[j-1] = L.elem[j]
,但j
最大只能是L.length-1
(最大下标)。
即:
for(int j = i; j <= L.length-1; j++){
L.elem[j-1] = L.elem[j];
}
第二种情况:
j
从i-1
开始,即L.elem[j]
就是要删除的元素,即L.elem[j] = L.elem[j+1]
,即可将元素前移,但j+1
最大只能是L.length-1
(最大下标),即j
不能大于L.length-1
,即j
最大只能是L.length-2
。
即:
for(int j = i-1; j <= L.length-2; j++) //或者写j < L.length-1
L.elem[j] = L.elem[j+1];
其余的函数,比如获取某个位置的元素、查找某个元素的位置都好理解,就不做记录了。下面就再多搞一个排序吧。
顺序表元素排序
代码:
//这里采用冒泡法,快速排序忘了怎么搞了。。。
void SortList(SqList &L){
int tmp;
for(int i = 0; i < L.length-1; i++)
for(int j = 0; j < L.length-i-1; j++)
if(L.elem[j] > L.elem[j+1]){
tmp = L.elem[j];
L.elem[j] = L.elem[j+1];
L.elem[j+1] = tmp;
}
}
大概以上就是关于顺序表中个人感觉不太好理解的内容了,欢迎大家指正!谢谢!