《数据结构与算法》 青岛大学-王卓 线性表(顺序存储)C++
根据B站视频内容,利用C++对算法进行编写,其中利用了模板技术,提高了代码的复用性。
B站链接:[https://www.bilibili.com/video/BV1nJ411V7bd?p=20]
- 数据类型:线性表
- 数据存储方式:顺序存储
优点:
存储密度大;
可以随机存取表中任一元素。
缺点:
在插入、删除某一元素时,需要移动大量元素;
浪费存储空间(必须是一大块连续的存储空间);
属于静态存储形式,数据元素的个数不能自由扩充。
(注:图片截取自《数据结构与算法》-青岛大学王卓bilibili视频)
/*
数据结构: 线性表
物理上 存储方式:顺序存储
功能上 初始化线性表、销毁线性表、清空线性表、插入元素、删除元素、排序、添加、是否为空、查找元素返回其位置、将表中第i个元素,赋值为e
*/
#include<iostream>
using namespace std;
#define MAX_SIZE 100
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status; // Status是函数的类型,其值是函数结果状态代码
// 创建线性表结构体,函数模板类型
template <class T>
struct SqList
{
T* elem; // 静态类型: elem[MAX_SIZE] 动态类型: T *elem;
int length;
};
// 线性表进行初始化
template <class T>
Status InitList_Sq(SqList<T>& L)
{
L.elem = new T[MAX_SIZE];
if (!L.elem)exit(OVERFLOW); // 创建失败,返回空值NULL,进行!NULL,则进入
L.length = 0; // 分配长度为0
return OK;
}
// 销毁线性表
template <class T>
void DestoryList(SqList<T>& L)
{
if (L.elem)
{
delete[] L.elem; // 释放存储空间
}
}
// 清空线性表
template <class T>
void ClearList(SqList<T>& L)
{
L.length = 0; // 将线性表长度置为0
}
// 求线性表长度
template <class T>
int GetLength(SqList<T>& L)
{
return L.length;
}
// 判断线性表是否为空
template <class T>
int IsEmpty(SqList<T>& L)
{
if (L.length == 0)return 1;
else return 0;
}
// 根据提供的位置i获取相应位置上的元素内容,随机存取
template <class T>
int GetElem(SqList<T>& L, int i, T& e)
{
if (i<1 | i>L.length)return ERROR; // 判断i值是否合理
e = L.elem[i - 1];
return OK;
}
// 按值查找,返回其位置,位置=索引+1 时间复杂度:O(n) 空间复杂度:O(1)
template <class T>
int GetIndex(SqList<T>& L, T& e)
{
T s = L.length;
for (size_t i = 0; i < s; i++)
if (L.elem[i]==e)return i+1; // 查找成功,返回位置=索引+1
return 0; // 查找失败
}
// 在线性表L中末尾插入新元素e
template <class T>
void BackInsert(SqList<T>& L, T e)
{
if (L.length > MAX_SIZE)exit(OVERFLOW);
L.elem[L.length] = e;
L.length++;
}
// 在线性表L中第i个位置插入新元素e 时间复杂度:O(n) 空间复杂度:O(1)
template <class T>
int ListInsert(SqList<T>& L, int i, T e)
{
if (i<0 || i>L.length+1 || L.length==MAX_SIZE)return 0; // 判断插入位置i是否合法
for (size_t j = L.length - 1; j >= i-1; j--) // 依次后移
{
L.elem[j+1] = L.elem[j];
}
L.elem[i - 1] = e; // 将新元素e插入第i个位置
L.length++; // 增加表长
return TRUE;
}
// 查看所有元素,打印列表
template <class T>
void ListPrint(SqList<T>& L)
{
for (size_t i = 0; i < L.length; i++)
{
cout << L.elem[i] << "\t";
}
cout << endl;
}
// 删除线性表中第i个位置元素,用e返回 时间复杂度:O(n) 空间复杂度:O(1)
template <class T>
int ListDelete(SqList<T>& L, int i, T& e)
{
if (i<1 || i>L.length)return 0; // 合法判断
e = L.elem[i - 1];
for (size_t j = i-1; j < L.length-1; j++) // 依次前移
{
L.elem[j] = L.elem[j + 1];
}
L.length--;
return OK;
}
// 线性表合并操作,去除重复,添加到尾部
template <class T>
void union_Sq(SqList<T>& La, SqList<T>Lb)
{
int La_len = La.length;
int Lb_len = Lb.length;
for (size_t i = 1; i <= Lb_len; i++)
{
T e;
GetElem(Lb, i, e);
if (!GetIndex(La, e)) ListInsert(La, ++La_len, e);
}
}
// 线性表合并操作 线性表应用2.7小节——后期添加
template <class T>
void MergeList_Sq(SqList<T> La, SqList<T> Lb, SqList<T>& Lc)
{
T* pa = La.elem; // 将指针pa指向La的第一个元素
T* pb = Lb.elem; // 将指针pb指向Lb的第一个元素
Lc.length = La.length + Lb.length; // Lc的长度为a、b的和
Lc.elem = new T[Lc.length];
T* pc = Lc.elem; // 将指针pc指向Lc的第一个元素
T* pa_last = La.elem+La.length-1; // 将指针pa_last指向La的最后一个元素
T* pb_last = Lb.elem+Lb.length-1; // 将指针pb_last指向Lb的最后一个元素
while (pa < pa_last && pb < pb_last)
{
if (*pa <= *pb) *pc++ = *pa++;
else *pc++ = *pb++;
}
while (pa <= pa_last) *pc++ = *pa++; // Lb到达表尾,将La中剩余元素加入Lc
while (pb <= pb_last) *pc++ = *pb++; // La到达表尾,将Lb中剩余元素加入Lc
}
int main()
{
SqList<int> L;
InitList_Sq(L);
ClearList(L);
BackInsert(L, 10);
BackInsert(L, 20);
BackInsert(L, 30);
BackInsert(L, 40);
ListInsert(L, 3, -10);
cout << GetLength(L) << endl;
cout << IsEmpty(L) << endl;
ListPrint(L);
int p;
ListDelete(L, 3, p);
ListPrint(L);
cout << p << endl;
DestoryList(L);
SqList<char> Lc;
InitList_Sq(Lc);
BackInsert(Lc, 'a');
BackInsert(Lc, 'b');
BackInsert(Lc, 'v');
BackInsert(Lc, 'd');
ListPrint(Lc);
ListInsert(Lc, 3, 'q');
ListPrint(Lc);
char ans;
ListDelete(Lc,2,ans);
ListPrint(Lc);
ClearList(Lc);
DestoryList(Lc);
return 0;
}