个人学习所记录笔记,便于复习查看,如有错误,请见谅。
一、顺序表的初始化
静态分配
const int MaxSize = 10;
struct SqList {
int data[MaxSize];
int length;
};
定义顺序表
// 初始化一个顺序表
void InitList(SqList &L) {
for (int i = 0; i < MaxSize; i++) {
L.data[i] = 0; // 将所有数据元素设置为默认初始值
}
L.length = 0; // 顺序表初始长度为0
}
动态分配
//动态分配,要用new ,delete函数 在c++中
const int InitSize =10;
struct SeqList{
int *data;
int MaxSize;
int length;
}
void InitLIst(SeqList &L){
//使用new函数,申请区域
L.data = new int[InitSize];
L.length=0;
L.MaxSize=InitSize;
}
动态分配扩充表
//添加动态数组的长度
//这个函数的作用是,在原有的顺序表空间上,
//增加 len 个元素的存储空间,并将原有的数据复制到新的空间中。
void IncreaseSize(SeqList& L, int len) {
int* p = L.data;
L.data = new int[L.MaxSize + len];
for (int i = 0; i < L.length; i++) {
L.data[i] = p[i];
}
L.MaxSize = L.MaxSize + len;
delete[] p; // 释放原来的内存空间
}
静态分配和动态分配的区别:
静态分配的顺序表在内存管理方面比较简单,但是无法动态扩展,而动态分配的顺序表可以动态扩展,但是内存管理相对较复杂。
二、顺序表的各种操作
1.插入操作
//插入操作
//在L表的第i个位置,插入数据e
void ListInsert(SqList& L, int i, int e) {
if (i < 1 || i > L.length + 1) { // 判断 i 的合法性,比如只有123有,但是你想插入5号位,只是不合法的
cout << "插入位置不合法!" << endl;
return;
}
if (L.length >= MaxSize) { // 如果顺序表已满,则需要扩容
cout << "插入位置不合法!" << endl;
}
//这段为主要内容
for (int j = L.length; j >= i; j--) { // 将元素向后移动
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e; // 插入元素
L.length++; // 更新顺序表长度
}
//也可以使用bool类型,return false 或者true
2.删除操作
bool ListDelete(SeqList& L, int i, int& e) {
if (i < 1 || i > L.length) { // 判断 i 的合法性
return false;
}
e = L.data[i - 1]; // 将被删除的元素值赋给 e
for (int j = i; j < L.length; j++) { // 将元素向前移动
L.data[j - 1] = L.data[j];
}
L.length--; // 更新顺序表长度
return true;
}
3.按位查找
//按位查找
int GetElem(SqList L, int i) {
if (i < 1 || i > L.length) { // 判断 i 的合法性
cout << "查找失败!" << endl;
return -1; // 返回 -1 表示查找失败
}
return L.data[i - 1]; // 返回顺序表中第 i 个元素的值
}
4.按值查找
//按值查找
int LocateElem(SqList L, int e) {
for (int i = 0; i < L.length; i++) { // 从第一个元素开始遍历
if (L.data[i] == e) { // 如果找到了相同元素
return i + 1; // 返回该元素在顺序表中的位置
}
}
return -1; // 没有找到,返回 -1 表示查找失败
}
5.遍历操作
// 输出顺序表中所有元素的值
void PrintList(SqList L) {
cout << "顺序表中的元素为:";
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
}
main函数中方法的调用
int main() {
// 声明一个顺序表
SqList L;
// 初始化顺序表
InitList(L);
// 在顺序表中插入一些元素
ListInsert(L, 1, 10);
ListInsert(L, 2, 20);
ListInsert(L, 3, 30);
ListInsert(L, 4, 40);
ListInsert(L, 5, 50);
// 输出顺序表中所有元素的值
PrintList(L);
//删除操作
int deletedValue;
if (ListDelete(L, 2, deletedValue)) {
cout << "删除成功!被删除的元素是:" << deletedValue << endl;
}
else {
cout << "删除失败!" << endl;
}
//按位查找操作
int foundValue = GetElem(L, 4);
if (foundValue != -1) {
cout << "第 4个位置上的元素值为:" << foundValue << endl;
}
//按值查找
int foundPos = LocateElem(L, 30);
if (foundPos != -1) {
cout << "元素 " << 30 << " 在顺序表中的位置为:" << foundPos << endl;
}
else {
cout << "元素 " << 30 << " 不在顺序表中!" << endl;
}
return 0;
}
完整代码实现:
#include <iostream>
#include <new> // 包含new和delete[]函数所需的头文件
using namespace std;
//静态分配,当超出容量的时候不可调,大小固定
const int MaxSize = 10;
struct SqList {
int data[MaxSize];
int length;
};
// 初始化一个顺序表
void InitList(SqList& L) {
for (int i = 0; i < MaxSize; i++) {
L.data[i] = 0; // 将所有数据元素设置为默认初始值
}
L.length = 0; // 顺序表初始长度为0
}
//插入操作
//在L表的第i个位置,插入数据e
void ListInsert(SqList& L, int i, int e) {
if (i < 1 || i > L.length + 1) { // 判断 i 的合法性,比如只有123有,但是你想插入5号位,只是不合法的
cout << "插入位置不合法!" << endl;
return;
}
if (L.length >= MaxSize) { // 如果顺序表已满,则需要扩容
cout << "插入位置不合法!" << endl;
}
//这段为主要内容
for (int j = L.length; j >= i; j--) { // 将元素向后移动
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e; // 插入元素
L.length++; // 更新顺序表长度
}
//也可以使用bool类型,return false 或者true
//删除操作
bool ListDelete(SqList& L, int i, int& e) {
if (i < 1 || i > L.length) { // 判断 i 的合法性
return false;
}
e = L.data[i - 1]; // 将被删除的元素值赋给 e
for (int j = i; j < L.length; j++) { // 将元素向前移动
L.data[j - 1] = L.data[j];
}
L.length--; // 更新顺序表长度
return true;
}
//按位查找
int GetElem(SqList L, int i) {
if (i < 1 || i > L.length) { // 判断 i 的合法性
cout << "查找失败!" << endl;
return -1; // 返回 -1 表示查找失败
}
return L.data[i - 1]; // 返回顺序表中第 i 个元素的值
}
//按值查找
int LocateElem(SqList L, int e) {
for (int i = 0; i < L.length; i++) { // 从第一个元素开始遍历
if (L.data[i] == e) { // 如果找到了相同元素
return i + 1; // 返回该元素在顺序表中的位置
}
}
return -1; // 没有找到,返回 -1 表示查找失败
}
// 输出顺序表中所有元素的值
void PrintList(SqList L) {
cout << "顺序表中的元素为:";
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
}
//有返回值,在main函数中得到被删除的数据
int main() {
// 声明一个顺序表
SqList L;
// 初始化顺序表
InitList(L);
// 在顺序表中插入一些元素
ListInsert(L, 1, 10);
ListInsert(L, 2, 20);
ListInsert(L, 3, 30);
ListInsert(L, 4, 40);
ListInsert(L, 5, 50);
// 输出顺序表中所有元素的值
PrintList(L);
//删除操作
int deletedValue;
if (ListDelete(L, 2, deletedValue)) {
cout << "删除成功!被删除的元素是:" << deletedValue << endl;
}
else {
cout << "删除失败!" << endl;
}
//按位查找操作
int foundValue = GetElem(L, 4);
if (foundValue != -1) {
cout << "第 4个位置上的元素值为:" << foundValue << endl;
}
//按值查找
int foundPos = LocateElem(L, 30);
if (foundPos != -1) {
cout << "元素 " << 30 << " 在顺序表中的位置为:" << foundPos << endl;
}
else {
cout << "元素 " << 30 << " 不在顺序表中!" << endl;
}
return 0;
}
三、顺序表的特点
1.随机访问, 可以在O(1)的时间内找到第i个元素
2.存储密度高
3.拓展容量不方便
4.插入,删除不方便,需要删除大量数据
四、各个操作的时间复杂度(简写,默认有O())
插入操作的时间复杂度
最好:插入表尾,不需要移动元素,o(1)
最坏:插入表头,移动n次,o(n)
平均:每个位置概率相同,o(n)
既为执行for循环的次数
删除操作时间复杂度
最好:1
最坏:n
平均:n
按位查找时间复杂度
o(1)
按值查找
最好:1
最坏:n
平均:n