一、线性表的抽象数据类型描述
类型名:线性表(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; } }