MOOC浙江大学的数据结构慕课学习记录——线性表
一、线性表的抽象数据类型描述
类型名:线性表(List)
数据对象集:线性表示n(>=0)个元素构成的有序序列(a1,a2,……,an)
操作集:线性表L∈List, 整数i表示位置,元素X∈ElementType
二、顺序表
1.定义
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];//存了一个数组,其最多能存MAXSIZE个元素
int Last;//最后一个元素的下标!
};
struct LNode L;
List PtrL;
访问下标为i的元素:L.Data[i]或PtrL->Data[i]
线性表的长度: L.Last+1 或 PtrL->Last+1;
2.操作
其基本操作有
1.List MakeEmpty();//初始化一个空线性表
2.ElementType FindKth(int K, List L);//返回下标为K的相应元素
3.int Find(ElementType X, List L);//在线性表L中查找X的第一次出现位置
4.void Insert(ElementType X, int i, List L);//在位序i前插入一个新元素X
5.void Delete(int i, List L);//删除指定位序i的元素
6.int Length(List L);//返回线性表的长度n
(1)创建空表
List MakeEmpty() {
List PtrL;
PtrL = (List)malloc(sizeof(struct LNode));
PtrL -> Last = -1;
return PtrL;
}
(2)查找元素X
int Find(ElementType X, List L) {
int i = 0;
while(i <= PtrL->Last && PtrL->Data[i] != X)
i++;
if(i > PtrL->Last) return -1;//如果没找到返回-1
else return i;//找到后返回的是存储位置 即下标
}
(3)插入
在第i(1 ≤ i ≤ n+1)个位置上插入一个值为X的新元素
void Insert(ElementType X, int i, List PtrL) {
int j;
if(PtrL->Last == MAXSIZE-1) {//表空间已满,则不能插入
printf("表满");
return;
}
if(i < 1 || i > PtrL->Last+2) {//检查输入是否合法
printf("位置不合法");
return;
}
for(j = PtrL->Last; j >= i-1; j--) //注意这里顺序不能从前往后
PtrL->Data[j+1] = PtrL->Data[j];
PtrL->Data[i-1] = X;
PtrL->Last++;//last仍指向最后元素!
return;
}
(4)删除
删除第i个元素(下标为i-1)
void Delete(int i, List PtrL) {
int j;
if(i < 1 || i > PtrL->Last+1) {//检查输入是否合法
printf("不存在第%d个元素",i);
return;
}
for (j = i; j <= PtrL->Last; j++)
PtrL->Data[j-1] = PtrL->Data[j];
PtrL->Last--;
return;
}
三、线性表的链式存储
重要!!链表即不要求逻辑上相邻的两个元素物理上也相邻,通过"链"建立起数据元素之间的逻辑关系。
其插入和删除不需要移动数据元素,只需要修改链。
1.定义
typedef struct LNode *List;
struct LNode {
ElementType Data;
List Next;//存放指向下一个结点的指针
}L;
List PtrL;
2.操作
其基本操作有
1.int Length(List PtrL)//求表长
2.List FindKth(int K, List PtrL) ;//按序号查找查找 查找链表中第K个元素
List Find(ElementType X, List PtrL) ; //按值查找: 查找元素K
3.List Insert(ElementType X, int i, List PtrL) ;//插入(在第i-1(1<=i<=n+1)个结点后插入一个值为X的新结点)
4.List Delete(int i, List PtrL);//删除操作(删除链表第i个位置上的结点)
(1)求表长
int Length(List PtrL) {
List p = PtrL;//p指向表的第一个节点
int j = 0;
while(p) {
p = p->Next;
j++;
}
return j;
}
(2)查找
1.按序号查找:FindKth
按序号查找查找 查找链表中第K个元素
List FindKth(int K, List PtrL) {
List p = PtrL;
int i = 1;
while (p != NULL && i < K) {
p = p->Next;
i++;
}
if(i == K) return p;//找到第K个返回指针
else return NULL;//否则返回空
}
2.按值查找:Find
按值查找: 查找元素K
List Find(ElementType X, List PtrL) {
List p = PtrL;
while(p != NULL && p->Data != X)
p = p->Next;
return p;
}
(3)插入操作
在第i-1(1 ≤ i ≤ n+1)个结点后插入一个值为X的新结点
(1)先构造一个新结点,用s指向 //malloc分配空间 将s的数据Data赋值为X
(2)再找到链表的第i-1个结点,用p指向
(3)然后修改指针,插入结点(p之后插入新结点是s)
// 先将p原先的指向next给s的next指针,再将p的next指针指向s
List Insert(ElementType X, int i, List PtrL) {
List p, s;
if(i == 1) {//新节点插入到表头
s = (List)malloc(sizeof(struct LNode));//申请、填装节点
s->Data = X;
s->Next = PtrL;
return s; //返回新表头指针
}
p = Find(i-1,PtrL); //查找第i-1个结点
if(p == NULL) { //第i-1个不存在 无法插入
printf("参数i错");
return NULL;
} else {
s = (List)malloc(sizeof(struct LNode)); //申请、填装结点
s->Data = X;
s->Next = p->Next; //新节点插入在第i-1个节点的后面
p->Next = s;
return PtrL;
}
}
(4)删除操作
删除链表第i个位置上的结点
(1)先找到链表的第i-1个结点,用p指向;//Find(i-1,PtrL);
(2)再用指针s指向要被删除的结点(p的下一个结点)//s = p->Next;
(3)然后修改指针,删除s所指向的结点//p->Next = s->Next;
(4)最后释放s所指结点的空间! //free(s)
List Delete(int i, List PtrL) {
List p, s;
if( i == 1) { //若要删除的是表的第一个结点
s = PtrL; //s指向第1个结点
if (PtrL != NULL) PtrL = PtrL->Next; //从链表中删除
else return NULL;
free(s); //释放被删除结点
return PtrL;
}
p = FindKth(i-1, PtrL); //查找第i-1个结点
if (p == NULL) {
printf("第%d个结点不存在", i-1);
return NULL;
} else if (p->Next == NULL) {
printf("第%d个结点不存在",i);
return NULL;
} else {
s = p->Next; //s指向第i个结点
p->Next = s->Next; //从链表中删除
free(s); //释放被删除结点的空间
return PtrL;
}
}