目录
线性表的顺序表示指用一组连续的存储单元来以此存储线性表的数据元素。
一、绪论
1.基本概念和术语
- 数据:可以输入计算机到计算机并被处理的所有符号的总合,对图像和声音进行编码也可使成为数据的范畴。
- 数据元素:可由若干数据项组合而成,数据项为数的最小组成部分,如一本书的书目信息为数据元素,则其书名、数目号称为数据项。
- 数据对象:为具有相同的性质的数据元素的集合,是数据的子集。
- 数据元素:是相互之间存在一种或多种特定关系的数据元素的集合。
- 逻辑结构:数据元素不可能孤立存在,之间存在某种特定的关系,称之为结构,根据特性分为集合(除同属于一个集合外无其他关系)、线性结构(存在一对一的关系)、树形结构(存在一对多的关系)、图状(网状)结构(存在多对多的关系。
- 数据结构的形式定义为二元组结构:Data.Structure=(D,S) 其中D表示数据的有限集。则S是D上关系的有限集。
- 物理结构(存储结构):数据结构在计算机中的表示(映像)。
- 位:计算机中表示信息的最小单位即二进制数的一位。
- 位串:通常由若干位组合起来表示一个数据元素,称位串为元素或结点。
- 数据域:位串中对应于各个数据项的子位串,即元素或结点可称为数据元素在计算机中的映像。
- 顺序映像(顺序存储结构):借助元素在存储器的相对位置来表示元素之间的逻辑关系。
- 非顺序映像(链式存储结构):借助指针来表示数据元素之间的逻辑关系。
- 任何一个算法的设计都取决于选定的数据(逻辑)结构,而算法的实现依赖于采用的存储结构。
- 数据类型:是一个值的集合和定义在这个值集上一组操作的总称。分为原子类型(不可分解)和结构类型(由若干成分按某种结构组成,即可以分解)。
- 抽象数据类型:指一个数学模型及定义在其上的一组操作,其定义仅取决于它的一组逻辑特性,而与其在计算机内部如何实现无关。按值的不同特性可分为原子类型、固定聚合类型、可变聚合类型。
- 多数据类型:指其值成分不确定的数据类型。
2.抽象数据类型的表示与实现
- 预定义常量和类型。
- 数据结构表示用类型定义typedef描述,数据元素型约定为ElemType。
- 赋值语句、选择语句、循环语句、结束语句(exit(异常代码))、输入输出语句、注释、基本函数、逻辑运算等。
3.算法和算法分析
- 算法:对特定问题求解步骤的一种描述,具备以下特性(有穷性、确当性、可行性、输入、输出)。
- 算法设计的要求:正确性、可读性、健壮性、效率与存储量的需求、
- 算法效率的度量:事后统计、事前分析
- 算法分析:一个算法是由控制结构(顺序、分支、循环)和原操作(固有数据类型的操作)构成。
- 算法的渐进时间复杂度(时间复杂度):O(n)即算法基本操作重复执行次数(频度)最多的操作,也称为渐进时间复杂度。有平均时间复杂度、最坏情况下的复杂度,
- 算法的存储空间需求(空间复杂度):S(n)作为程序存储空间的量度,一般由数据空间、程序空间和辅助空间组成,如果在运行过程中未开辟新的空间则为1。
二、线性表
线性表:数据元素的有限序列,在复杂线性表中,一个数据数据元素可由多个数据项组成,此时把数据元素叫做记录,含有大量记录的线性表叫文件。
前驱:
后继:
1、线性表的顺序表示和实现
线性表的顺序表示指用一组连续的存储单元来以此存储线性表的数据元素。
代码实现以及基本操作
#include<iostream>
using namespace std;
//创建链表
struct SqList {
int * data; //链表头结点
int size; //链表数据大小
int length; //链表长度
};
//创建初始顺序表
bool InsList(SqList& L, int i, const int e); //声明插入数据函数
bool Initlist(SqList& L, int s) {
if (s <= 0) s = 10;//为设置初始长度,则定义为10.
L.data = new int[s];
if (L.data == NULL) return false; //初始化失败
L.length = s;//长度为s.
L.size = 0;//数据个数为0,
//插入数据
int i, n;
cout << "请输入填入的数据个数:" << endl;
cin >> i;
cout << "请输入元素:" << endl;
for (int j = 0; j < i; j++) {
cin >> n;
InsList(L, j + 1, n);
}
}
//销毁顺序表
void DestoryList(SqList& L) {
delete[] L.data;
L.data = NULL;
L.length = 0;
L.size = 0;
//也可直接将数字个数设置为零,后续直接进行数据覆盖。
}
//遍历顺序表
void DisList(const SqList & L) {
if (L.length == 0) {
cout << "为空表" << endl;
}
else {
for (int i = 00; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
}
}
//插入数据函数 在指定序号前
bool InsList(SqList& L, int i, const int e) {
if (i<1 || i>L.length + 1) return false;//空间不足或满了
//如果空间不足 采用二倍扩容
if (L.length == L.size) {
int* temp = new int[2 * L.size];
if (temp == NULL) return false;
for (int i = 0; i < L.length; i++) {
temp[i] = L.data[i];
}
delete[] L.data;
L.data = temp;
L.size = L.size * 2;
}
//插入数字 前插法
for (int k = L.length - 1; k >= i - 1; k--) {
L.data[k + 1] = L.data[k]; //移动数据
L.data[i - 1] = e;
L.length++;
return true;
}
}
//删除指定序号的数据元素
bool DeList(SqList& L, int i) {
if (i >= 1 && i < L.length) {
for (int k = i; k < L.length; k++) {
L.data[k - 1] = L.data[k];
}
L.length--;
return true;
}
return false;
}
//获得指定序号的元素
int GetData(const SqList& L, int i) {
int e = 0;
if (i >= 1 && i <= L.length) {
e = L.data[i - 1];
return e;
}
else return 0;
}
//获取顺序表中的最大数据元素
int GetMax(const SqList& L) {
int e = L.data[0];
int i = 0;
if (L.length == 0) {
cout << "顺序表为空!" << endl;
return 0;
}
else {
for (i = 0; i < L.length; i++) {
if (e < L.data[i]) e = L.data[i];
}
return e;
}
}
//逆置顺序表
void NzList(SqList& L) {
int m = L.length - 1;
int t;
for (int i = 0; i <= m; i++) {
t = L.data[i];
L.data[i] = L.data[m];
L.data[m] = t;
m--;
}
}
int main() {
SqList L; //实例化顺序表
Initlist(L, 2); //初始化
//实现相关功能调用相关函数即可
return 0;
}
2、链式顺序表的基本实现
//链式顺序表的实现
#include<iostream>
using namespace std;
typedef struct Node{
int data; //元素的值
struct Node* next; //后继元素地址
}ListNode,*LinkList;
//头插法创建链表
LinkList HBuildList() {
ListNode* L = new Node; //创建头结点
ListNode* p; //结构体指针
L->next = NULL;
int a;
while (1) {
cin >> a;
if (a == 0) break;
p = new Node;
p->data = a;
p->next = L->next;
L->next = p;
}
return L;
}
//尾插法创建链表
LinkList WBuildList() {
ListNode* L = new ListNode;
LinkList p, r = L;
L->next = NULL;
int a;
while (1) {
cin >> a;
if (a == 0) break;
p = new ListNode;
p->data = a;
r->next = p;
r = p;
}
r->next = NULL;
return L;
}
//链表的遍历
void ShowList(LinkList L) {
ListNode* p = L->next;
while (p) {
cout << p->data<< " ";
p = p->next;
}
}
//在第i个结点前插入元素
bool InsertList1(LinkList& L, int i, int e) {
ListNode* p = L;
ListNode* s;
int j = 0;
while (p && j < i - 1) {
p = p->next;
j++;
}
if (p == NULL) return false;
else
{
s = new Node;
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
}
//在第i个结点后插入元素
bool InsertList2(LinkList& L, int i,int e) {
ListNode* p = L;
ListNode* s;
int j = 0;
while (p->next && j < i) {
p = p->next;
j++;
}
if (p == NULL) return false;
else
{
s = new Node;
s->data= e;
s->next = p->next;
p->next = s;
return true;
}
}
//删除第i个结点的元素
bool DeleteNum(LinkList& L, int i) {
ListNode* p = L;
ListNode* s;
int j = 0;
while (p && j < i - 1) {
p = p->next;
j++;
}
if (p->next == NULL) return false;
else
{
s = p->next->next;
//判断第I个元素是否为尾结点
if (s == NULL)
{
delete p->next;
p->next = NULL;
}
else {
delete p->next;
p->next = s;
}
return true;
}
}
//按值查找元素
bool FindList(LinkList& L, int e) {
ListNode* p = L->next;
int j = 1;
bool f = false;
while (p)
{
j++;
if (p->data == e) {
f = true;
break;
}
p = p->next;
}
return f;
}
int main(){
//实现相关功能调用函数即可
ListNode *L=HBuildList(); //创建链表
ShowList(L);
return 0;
}
顺序存储 | 链式存储 | |
---|---|---|
优点 | 1.随机元素的查找、以及替换比较方便。 2.求表长较容易。 | 1.插入、删除和替换元素比较方便。 |
缺点 | 1.插入、删除个别元素不大方便。 | 1.不容易寻找指定序号的元素。 2.不容易计算表长。 |