本篇主要专注与于解析操作代码的各部分意义,包含顺序表的增删改查算法实现
下面进入正题:
实现顺序表首先需要创建结构体,结构体内要包含顺序表的基本信息,包括但不限于顺序表长度、元素数组,下面是一段开局代码,一个静态顺序表的结构体定义。为方便理解,尽可能地简化了语法并在全局区创建结构体实例对象,便于调用,代码仅仅表现大体逻辑框架,接近伪代码表述
语言描述的伪代码写在了注释里
#include <iostream>
using namespace std;
#define MAXSIZE 100
struct linearlist {//直接在栈区创建对象
int curlength;
int data[MAXSIZE];
};
linearlist list1;//全局变量list1
Traverse() ——元素遍历函数
为了兼顾到算法的健壮性,需要考虑空表时反应,空表时提醒用户无法遍历。所以遍历函数执行前应该先判断是否为空表,若是空表则返回布尔值
bool Empty() {
return list1.curlength == 0;//判断顺序表元素长度是否为0
}
void Traverse() {
if (Empty()) {//使用Empty函数判断是否空表
cout << "Sequence list is empty";
}
else {//不是空表的时候执行以下代码
cout << "result:";
for (int i = 0; i < list1.curlength; ++i) {//for循环打印data[]的所有元素
cout << list1.data[i] << " ";
}
cout << endl;
}
}
Search() ——特定数值搜索函数
int Search(int value) {//输入要查找的数值
for (int i = 0; i < list1.curlength; i++) {//遍历data[]
if (value == list1.data[i])//若数值等于其中一个元素值
return i;//返回这个元素的下标
}
return -1;
}
Insert()——元素插入函数
兼顾算法健壮性,插入元素时要考虑插入元素的下标是否合法,不合法需要重新输入数据,并且判断顺序表是否已满,满表时无法执行插入操作,需要先扩大顺序表容量,然后再执行插入操作。核心语句是for,插入前将顺序表中从最后一位元素开始依次向后一位拷贝,循环执行到目标元素处,为插入位置腾出空间
void Insert(int value, int i) {
if (i < 0 || i>list1.curlength) {
cout << "the data is illegal" << endl;
return;
}
if (list1.curlength == MAXSIZE)//若顺序表已满
Resize();//则扩大存储空间
for (int j = list1.curlength; j >= i; j--) {//把即将插入的下标元素以及后面的元素向后推一位
list1.data[j] = list1.data[j - 1];
}
list1.data[i] = value;//将value写入data[i]
list1.curlength++;//元素实际长度+1
}
Delete()——元素删除函数
删除元素需要考虑目标元素所在下标,先判定输入的参数是否在合法范围内,若不合法则返回。核心在于目标元素后面的数据依次向前拷贝,操作从目标元素后一位循环执行到最后一位元素,将目标数据覆盖,达到逻辑和物理方面的清除
void Delete(int i) {
if (i < 0 || i > list1.curlength)
return ;
for (int j = i; j < list1.curlength; j++)
list1.data[j - 1] = list1.data[j];
list1.curlength--;
}
Inverse()——元素逆序函数
涉及到元素的交换问题,需要临时变量作为暂存站。首先将第一位元素拷贝至tmp,然后最后一位元素值拷贝到第一位元素,tmp将暂存值再拷贝到最后一位元素处,完成一次元素交换,然后是第二位元素与倒数第二位元素交换,依此类推...
void Inverse() {
int tmp;//临时变量
for (int i = 0; i < list1.curlength / 2; i++) {
tmp = list1.data[i];//临时变量暂存元素值
list1.data[i] = list1.data[list1.curlength - 1 - i];//最后一位元素拷贝到第一个下标处
list1.data[list1.curlength - 1 - i] = tmp;//暂存值拷贝到最后一个元素处,完成交换
}
}
Resize()——空间扩充函数
Caution!!!: Resize用于扩容顺序表,但这个函数只能用于在堆区创建的顺序表,在栈区创建的顺序表无法正常使用这个函数,因为栈区数据没有空间动态性。这个算法可以粗略理解为创建了一个长度为原表长度两倍的顺序表,并将原顺序表数据一一拷贝到新的顺序表内,再删除原来的顺序表
void Resize() {//Resize用于扩容顺序表,但这个函数只能用于在堆区创建的顺序表,在栈区创建的表无法使用
Elemtype * p = list1.data;
int a = MAXSIZE * 2;
list1.data = new Elemtype[a];
for (int i = 0; i < list1.curlength; i++)
list1.data[i] = p[i];
delete[] p;
}
Visit()——元素访问函数
涉及到了下标合法性问题,依旧是先完成参数合法判断再开始执行函数
int Visit(int i) {
if ( i < 0 || i > list1.curlength)
return 0;
return list1.data[i];
}