目录
基本概念
- 线性表是最常用且简单的一种数据结构,一个线性表是n个元素的有限序列
- 线性结构:在数据元素的非空有限集合中,有以下几种特点:
存在唯一的一个被称作"第一个的元素" |
存在唯一的一个被称作"最后一个的元素" |
除第一个以外,集合中的每一个数据元素均只有一个前驱 |
除最后一个以外,集合中的每一个数据元素均只有一个后继 |
顺序表的特点
- 顺序存储结构是一种随机存取的存储结构
- 无需为表中的数据元素之间的逻辑关额外的存储空间
- 能够快速的获取索引位置上的数据元素信息
- 容易造成存储空间的碎片化
部分函数算法分析
- 顺序表在指定索引位置插入数据元素
//顺序表在指定索引位置进行数据元素的插入
Status InsertSqList(SqList& L,int index,ElemType elem) {
//判断插入索引位置是否合法
if (index < 1 || index > L.length + 1) {
cout << "插入索引位置不合法" << endl;
return ERROR;
}
//判断顺序表是否已满
if (L.length >= L.list_size) {
//为顺序表扩容
ElemType* newbase;
newbase = (ElemType*)realloc(L.elem, (L.list_size + LIST_INCREMENT) * sizeof(ElemType));
//判断扩容操作是否成功
if (!newbase)
exit(OVERFLOW);
//将新分配的空间基地址赋值给顺序表
L.elem = newbase;
//顺序表空间增大
L.list_size += LIST_INCREMENT;
}
//q位置为插入数据位置
ElemType* q = &(L.elem[index - 1]);
//将插入位置及其以后的所有元素后移一位
for (ElemType* p = &(L.elem[L.length - 1]); p >= q; --p) {
*(p + 1) = *p;
}
*q = elem;
//存储的元素个数加一
++L.length;
return OK;
}
在插入数据前,应先判断插入的位置是否合法。因为顺序表空间是有限的,在插入数据前需要判断顺序表空间是否已满,是否需要扩容
顺序表的第一个数据元素的索引为0,所以在插入的位置索引为(index - 1),找到该位置后,需将插入位置即以后的所有元素都向后移动一位,从最后一个数据元素依次开始移动,直到到达插入位置元素移动,循环终止
- 顺序表在指定索引位置上删除数据
//顺序表删除指定位置上的数据元素
Status DeleteSqList(SqList& L, int index) {
//判断删除元素的索引位置是否合法
if (index < 1 || index > L.length) {
cout << "删除索引位置信息不合法" << endl;
return ERROR;
}
//q位置为删除数据的位置
ElemType* q = &(L.elem[index - 1]);
ElemType* p = &(L.elem[L.length - 1]);
//将q位置之后的数据元素向前移动一位
for (++q; q <= p; ++q) {
*(q - 1) = *q;
}
--L.length;
return OK;
}
先判断删除索引位置是否合法,即是否超出顺序表内存在的元素个数长度,是否小于1
找到删除位置的索引后,需将索引位置后的每一个元素都向前移动一个位置,即删除索引位置上的数据信息被后一个覆盖,注意:最后一个元素(L.elem[L.length - 1])仍然存在顺序表内,没有被覆盖,但是顺序表内已存在的元素长度(L.length - 1),所以在遍历的时候不会遍历到该数据元素
线性表的顺序表示和实现
- global.h
- SqList.h
- SqListTest.cpp
global.h
相关头文件的引用,以及相应全局变量、常量的声明
#pragma once
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define EQ(a,b) ((a) == (b))
#define LT(a,b) ((a) < (b))
#define LQ(a,b) ((a) <= (b))
#define MT(a,b) ((a) > (b))
#define MQ(a,b) ((a) >= (b))
typedef int Status;
SqList.h
顺序表的结构定义,以及顺序表的相关操作算法
#pragma once
#include"global.h"
/*----------线性表的动态分配顺序存储结构----------*/
//线性表初始空间分配的大小
#define LIST_INIT_SIZE 100
//空间扩展的分配增量
#define LIST_INCREMENT 10
//自定义的元素类型
#define ElemType int
//定义线性表
typedef struct SqList {
//数据存储空间基地址
ElemType* elem;
//顺序表内存在的元素个数
int length;
//当前顺序表的存储空间大小
int list_size;
}SqList;
//顺序表的初始化(操作成功返回OK)
Status InitSqList(SqList& L) {
//为线性表分配100*sizeof(ElemType)空间大小
L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
//判断空间分配是否成功
if (!L.elem)
exit(OVERFLOW);
//为初始顺序表的length、与list_size赋值
L.length = 0;
L.list_size = 100;
return OK;
}
//顺序表的遍历
void ShowSqList(SqList L) {
for (int i = 0; i < L.length; i++) {
cout << L.elem[i] << " ";
}
cout << endl;
}
//顺序表数据元素的顺序添加
Status AddSqList(SqList& L,ElemType elem) {
//判断顺序表是否已满
if (L.length >= L.list_size) {
//为顺序表扩容
ElemType* newbase;
newbase = (ElemType*)realloc(L.elem, (L.list_size + LIST_INCREMENT) * sizeof(ElemType));
//判断扩容操作是否成功
if (!newbase)
exit(OVERFLOW);
//将新分配的空间基地址赋值给顺序表
L.elem = newbase;
//顺序表空间增大
L.list_size += LIST_INCREMENT;
}
//将数据按顺序添加至顺序表中
L.elem[L.length++] = elem;
return OK;
}
//顺序表在指定索引位置进行数据元素的插入
Status InsertSqList(SqList& L,int index,ElemType elem) {
//判断插入索引位置是否合法
if (index < 1 || index > L.length + 1) {
cout << "插入索引位置不合法" << endl;
return ERROR;
}
//判断顺序表是否已满
if (L.length >= L.list_size) {
//为顺序表扩容
ElemType* newbase;
newbase = (ElemType*)realloc(L.elem, (L.list_size + LIST_INCREMENT) * sizeof(ElemType));
//判断扩容操作是否成功
if (!newbase)
exit(OVERFLOW);
//将新分配的空间基地址赋值给顺序表
L.elem = newbase;
//顺序表空间增大
L.list_size += LIST_INCREMENT;
}
//q位置为插入数据位置
ElemType* q = &(L.elem[index - 1]);
//将插入位置及其以后的所有元素后移一位
for (ElemType* p = &(L.elem[L.length - 1]); p >= q; --p) {
*(p + 1) = *p;
}
*q = elem;
//存储的元素个数加一
++L.length;
return OK;
}
//顺序表删除指定位置上的数据元素
Status DeleteSqList(SqList& L, int index) {
//判断删除元素的索引位置是否合法
if (index < 1 || index > L.length) {
cout << "删除索引位置信息不合法" << endl;
return ERROR;
}
//q位置为删除数据的位置
ElemType* q = &(L.elem[index - 1]);
ElemType* p = &(L.elem[L.length - 1]);
//将q位置之后的数据元素向前移动一位
for (++q; q <= p; ++q) {
*(q - 1) = *q;
}
--L.length;
return OK;
}
SqListTest.cpp
#include"SqList.h"
int main() {
SqList list;
InitSqList(list);
int count = 0;
cout << "为顺序表添加多少数据元素:" << endl;
cin >> count;
cout << "请输入" << count << "个数据元素:" << endl;
ElemType elem;
for (int i = 0; i < count; i++) {
cin >> elem;
AddSqList(list, elem);
}
ShowSqList(list);
cout << "----------数据插入操作----------" << endl;
cout << "请输入插入索引位置:" << endl;
int index = 0;
cin >> index;
cout << "请输入插入的数据元素:" << endl;
cin >> elem;
InsertSqList(list, index, elem);
ShowSqList(list);
cout << "----------数据删除操作----------" << endl;
cout << "请输入删除索引位置:" << endl;
cin >> index;
DeleteSqList(list, index);
ShowSqList(list);
}
运行结果
为顺序表添加多少数据元素:
5
请输入5个数据元素:
12 23 34 54 56
12 23 34 54 56
----------数据插入操作----------
请输入插入索引位置:
3
请输入插入的数据元素:
44
12 23 44 34 54 56
----------数据删除操作----------
请输入删除索引位置:
2
12 44 34 54 56