目录
1--线性表的基本概念
线性表(Linear List):由同类型数据元素构成的有序序列的线性结构;
线性表中元素的个数称为线性表的长度;
线性表没有元素时,称为空表;
线性表起始位置称为表头,结束位置称为表尾;
线性表的抽象数据类型描述:
类型名称:线性表(List)
数据对象集:线性表是由 n 个元素构成的有序序列()
操作集:线性表 L ∈ List,整数 i 表示位置,元素 X ∈ ElementType,其基本操作如下:
① List MakeEmpty(); 初始化一个空线性表L;
② ElementType FindKth(int K, List L); 根据位序K,返回相应元素;
③ int Find(ElementType X, List L); 在线性表 L 中查找 X 第一次出现的位置;
④ void insert(ElementType X, int i, List L); 在位序 i 前插入一个新元素 X;
⑤ void Delete(int i, List L); 删除指定位序 i 的元素;
⑥ int Length(List L); 返回线性表 L 的长度 n;
2--线性表的顺序存储
利用数组的连续存储空间顺序存放线性表的各元素,其定义方式如下:
#define ElementType int
#define MAXSIZE 10
typedef struct LNode *List; // 别名
struct LNode{
ElementType Data[MAXSIZE];
int Last; // 存放最后一个元素的位置
};
// struct LNode L; // 创建线性表L
// List L; // 创建线性表L
// 线性表的长度: L->Last+1 (因为Last从0开始)
// 访问线性表的元素: L->Data[i]
2-1--建立空表
// 建立空表
List MakeEmpty(){
List L;
L = (List)malloc(sizeof(struct LNode));
L->Last = -1;
return L;
}
2-2--查找元素
// 查找元素
int Find(ElementType X, List L){
for(int i = 0; i <= L->Last; i++){
if(L->Data[i] == X) return i;
}
return -1; // 未找到
}
2-3--插入元素
// 插入元素
void Insert(ElementType X, int i, List L){ // i从0开始
if(L->Last == MAXSIZE - 1){
std::cout << "Error: The List is Full!" << std::endl;
return;
}
if(i < 0 || i > L->Last+1){
std::cout << "Error: Illegal insertion position!" << std::endl;
return;
}
for(int j = L->Last; j>=i; j--){
L->Data[j+1] = L->Data[j];
}
L->Data[i] = X;
L->Last++;
return;
}
2-4--删除元素
// 删除元素
void Delete(int i, List L){ // i从0开始
if(i < 0 || i > L->Last){
std::cout << "Error: The position is Illegal" << std::endl;
return;
}
for(int j = i; j < L->Last; j++){
L->Data[j] = L->Data[j+1];
}
L->Last--; // 如果删除最后一个元素,只需要将末尾指针前移即可
return;
}
2-5--遍历打印
// 打印线性表
void PrintList(List L){
// 遍历打印元素
for(int i = 0; i < L->Last+1; i++){
std::cout << L->Data[i] << " ";
}
std::cout<< std::endl;
}
2-6--测试代码
#include "iostream"
#define ElementType int
#define MAXSIZE 10
typedef struct LNode *List; // 别名
struct LNode{
ElementType Data[MAXSIZE];
int Last; // 存放最后一个元素的位置
};
// struct LNode L; // 创建线性表L
// List L; // 创建线性表L
// 线性表的长度: L->Last+1 (因为Last从0开始)
// 访问线性表的元素: L->Data[i]
// 建立空表
List MakeEmpty(){
List L;
L = (List)malloc(sizeof(struct LNode));
L->Last = -1;
return L;
}
// 查找元素
int Find(ElementType X, List L){
for(int i = 0; i <= L->Last; i++){
if(L->Data[i] == X) return i;
}
return -1; // 未找到
}
// 插入元素
void Insert(ElementType X, int i, List L){ // i从0开始
if(L->Last == MAXSIZE - 1){
std::cout << "Error: The List is Full!" << std::endl;
return;
}
if(i < 0 || i > L->Last+1){
std::cout << "Error: Illegal insertion position!" << std::endl;
return;
}
for(int j = L->Last; j>=i; j--){
L->Data[j+1] = L->Data[j];
}
L->Data[i] = X;
L->Last++;
return;
}
// 删除元素
void Delete(int i, List L){ // i从0开始
if(i < 0 || i > L->Last){
std::cout << "Error: The position is Illegal" << std::endl;
return;
}
for(int j = i; j < L->Last; j++){
L->Data[j] = L->Data[j+1];
}
L->Last--; // 如果删除最后一个元素,只需要将末尾指针前移即可
return;
}
// 打印线性表
void PrintList(List L){
// 遍历打印元素
for(int i = 0; i < L->Last+1; i++){
std::cout << L->Data[i] << " ";
}
std::cout<< std::endl;
}
int main(int argc, char* argv[]){
List L = MakeEmpty(); // 建立空表
// 插入元素
Insert(1, 0, L);
Insert(2, 1, L);
Insert(3, 2, L);
Insert(4, 1, L);
PrintList(L); // 打印线性表
std::cout<< "The length of list L: " << L->Last+1 << std::endl;
// 查找元素
int pos = Find(4, L);
std::cout << "The elem " << 4 << " is in pos: " << pos << std::endl;
// 删除元素
Delete(1, L); // 删除idx为1的元素;
Delete(L->Last, L); // 删除最后一个的元素;
Delete(0, L); // 删除第一个元素
PrintList(L); // 打印线性表
std::cout<< "The length of list L: " << L->Last+1 << std::endl;
return 0;
}
3--线性表的链式存储
链式存储不强制要求逻辑相邻的两个元素必须物理相邻;可通过链建立起数据元素之间的逻辑关系;线性表链式存储的定义方式如下:
#define ElementType int
#define MAXSIZE 10
typedef struct LNode *List; // 别名
struct LNode{
ElementType Data; // 数据域
List Next; // 指针域
};
// struct LNode L; // 创建线性表L
// List L; // 创建线性表L
初始化带头结点的单链表:
// 初始化带头结点的链表
bool InitList(List &L){
L = (LNode*)malloc(sizeof(LNode)); // 头结点
L->Next = NULL;
return true;
}
遍历打印链表:
// 打印链表(带头结点)
void PrintList(const List L){
// 从第一个数据结点开始遍历
for(LNode *p = L->Next; p != NULL; p = p->Next){
std::cout << p->Data << " ";
}
std::cout << std::endl;
}
2-1--计算表长
// 求表长(不包括头节点)
int Length(List L){
List p = L; // 指向头结点
int num = -1;
while(p){
p = p->Next;
num++;
}
return num;
}
2-2--查找操作
① 按序号查找:
// 按序号查找
List FindKth(int K, const List L){
List p = L; // 指向头结点
int idx = 0;
while(p != NULL && idx < K){
p = p->Next;
idx++;
}
if(idx == K) return p; // 找到第K个,返回指针
else return NULL; // 未找到,返回空
}
② 按值查找:
// 按值查找
List FindElem(ElementType X, List L){
List p = L; // 指向头结点
while(p != NULL && p->Data != X){
p = p->Next;
}
return p;
}
2-3--插入操作
主要操作步骤:
① 判断插入位置是否合法;
② 找到第 i-1 个结点的位置;
③ 为新结点申请内存空间
④ 更新指针域;
// 插入操作(带头节点)
bool ListInsert(List &L, int i, ElementType e){
if(i < 1){ // 不合法
return false;
}
LNode *p = L;
for(int j = 0; p != NULL && j < i - 1; j++){
p = p->Next; // p指向 i-1 结点
}
if(p == NULL){ // 不合法
return false;
}
LNode* s = (LNode*)malloc(sizeof(LNode)); // 申请新结点内存空间
s->Data = e;
s->Next = p->Next;
p->Next = s;
return true;
}
2-4--删除操作
主要操作步骤:
① 判断删除位置是否合法;
② 找到删除结点的前一个结点,更新其指针域;
③ 释放待删除的结点;
// 删除操作
bool Delete(int i, List &L){
if(i < 1){
return false;
}
LNode *pos = FindKth(i - 1, L); // 找到第 i-1 个数据结点
if(pos == NULL){ // 前一个数据结点不存在
std::cout << "The Node is not exist!" << std::endl;
return false;
}
else if(pos->Next == NULL){ // 前一个数据结点是最后一个结点
std::cout << "The Node is not exist!" << std::endl;
return false;
}
else{
LNode *s = pos->Next; // 要删除的结点
pos->Next = s->Next;
free(s);
return true;
}
}
2-5--测试代码
#include "iostream"
#define ElementType int
#define MAXSIZE 10
typedef struct LNode *List; // 别名
struct LNode{
ElementType Data;
List Next; // 存放最后一个元素的位置
};
// struct LNode L; // 创建线性表L
// List L; // 创建线性表L
// 初始化带头结点的链表
bool InitList(List &L){
L = (LNode*)malloc(sizeof(LNode)); // 头结点
L->Next = NULL;
return true;
}
// 求表长(不包括头节点)
int Length(List L){
List p = L; // 指向头结点
int num = -1;
while(p){
p = p->Next;
num++;
}
return num;
}
// 插入操作(带头节点)
bool ListInsert(List &L, int i, ElementType e){
if(i < 1){ // 不合法
return false;
}
LNode *p = L;
for(int j = 0; p != NULL && j < i - 1; j++){
p = p->Next; // p指向 i-1 结点
}
if(p == NULL){ // 不合法
return false;
}
LNode* s = (LNode*)malloc(sizeof(LNode)); // 申请新结点内存空间
s->Data = e;
s->Next = p->Next;
p->Next = s;
return true;
}
// 按序号查找
List FindKth(int K, const List L){
List p = L; // 指向头结点
int idx = 0;
while(p != NULL && idx < K){
p = p->Next;
idx++;
}
if(idx == K) return p; // 找到第K个,返回指针
else return NULL; // 未找到,返回空
}
// 按值查找
List FindElem(ElementType X, List L){
List p = L; // 指向头结点
while(p != NULL && p->Data != X){
p = p->Next;
}
return p;
}
// 删除操作
bool Delete(int i, List &L){
if(i < 1){
return false;
}
LNode *pos = FindKth(i - 1, L); // 找到第 i-1 个数据结点
if(pos == NULL){ // 前一个数据结点不存在
std::cout << "The Node is not exist!" << std::endl;
return false;
}
else if(pos->Next == NULL){ // 前一个数据结点是最后一个结点
std::cout << "The Node is not exist!" << std::endl;
return false;
}
else{
LNode *s = pos->Next; // 要删除的结点
pos->Next = s->Next;
free(s);
return true;
}
}
// 打印链表
void PrintList(const List L){
for(LNode *p = L->Next; p != NULL; p = p->Next){
std::cout << p->Data << " ";
}
std::cout << std::endl;
}
int main(int argc, char* argv[]){
List L;
InitList(L); // 初始化带头结点的链表
ListInsert(L, 1, 10);
ListInsert(L, 2, 20);
ListInsert(L, 3, 30);
ListInsert(L, 4, 40);
// 计算表长
int len = Length(L);
std::cout << "The length of the list is: " << len << std::endl;
// 打印链表
PrintList(L);
LNode *p1 = FindKth(2, L); // 查找第二个数据元素
std::cout << "Find the elem: " << p1->Data << std::endl;
LNode *p2 = FindElem(30, L); // 查找第二个数据元素
std::cout << "Find the elem: " << p2->Data << std::endl;
Delete(4, L);// 删除第4个数据结点
Delete(1, L);// 删除第1个数据结点
PrintList(L);
return 0;
}