顺序表简介:
顺序表是简单的一种线性结构,他们可以说是连续存储元素的,也可以称之为数组。顺序表可以快速定位到第几个元素的位置,中间不允许有空值。插入、删除时需要移动大量的元素!
顺序表的三个要素:
- 用elems记录存储位置的基地址;
- 分配一段连续的存储空间size;
- 用length记录实际的元素个数,即顺序表的长度。
顺序表的结构体定义
#define MAX_SIZE 100
struct SEQUENCE {
int *elems; // 存储整型的顺序表的基地址
int length; // 顺序表的长度
int size; // 顺序表的总空间大小
}
顺序表的定义与初始化
#define MAX_SIZE 100
// 定义
struct SEQUENCE {
int* memory; // 首地址
int length; // 大小/元素个数
int size; // 内存大小
};
// 初始化
bool initSEQUENCE(struct SEQUENCE& L) {
L.memory = new int[MAX_SIZE]; // 分配内存
if (!L.memory) { // 判断是否分配失败
return false;
}
L.length = 0; // 空表长度为0
L.size = MAX_SIZE; // 顺序表的总空间大小
return true;
}
如下图:
初始化只是给顺序表分配内存大小!
尾部插入数据
// 尾部插入数据
bool insertSEQUENCE(struct SEQUENCE& L, int e) { // 参数一:顺序表的引用; 参数二:需要插入的元素
if (L.length == L.size) return false; // 合法性检查,如果顺序表已满,则无法插入
L.memory[L.length] = e; // 将元素插入下标为length的位置
L.length++; // 顺序表的长度加1
return true;
}
如下图:
在尾部插入元素,只需要将该元素赋值给length下标,并将length++即可。
中间插入数据
// 中间插入数据
bool insert(struct SEQUENCE& L, int i, int e) { // 参数一:顺序表的引用;参数二:插入位置(下标);参数三:插入元素
if (i < 0 || i >= L.length) return false; // 合法性检查,中间插入元素,插入位置i不可能大于等当前元素的长度length
if (L.length == L.size) return false; // 合法性检查,如果顺序表已满,则无法插入
for (int j = L.length - 1; j >= i; j--) { // 把元素都往后移动一个位置,直到遇到插入位置为止
L.memory[j+1] = L.memory[j];
}
L.memory[i] = e; // 赋值需要插入的元素到下标i的位置
L.length++; // 顺序表的长度加1
return true;
}
如下图:
中间插入一个元素,需要将插入位置的后面所有元素都往后移动一个位置,然后再插入。
元素删除
// 元素删除
bool deleteSEQUENCE(struct SEQUENCE& L, int i) { // 参数一:顺序表的引用;参数二:删除位置(下标)
if (i < 0 || i >= L.length) return false; // 合法性检查,删除的元素,位置(下标)i不可能大于等当前元素的长度length
if (i == L.length - 1) { // 删除最后一个元素
L.length--; // 只需要将length长度减一即可
return true;
}
for (int j = i; j < L.length - 1; j++) { // 删除中间某个元素
L.memory[j] = L.memory[j + 1]; // 删除位置的后续元素往前移
}
L.length--; // length长度减一
return true;
}
如下图:
删除某个元素,只需将其后面所有的元素都往前移动一个位置,将其覆盖掉,最后将length减一即可。
顺序表销毁
当程序要结束时,也是需要将顺序表的内存释放掉,应为他的内存是从堆上分配的!
// 释放顺序表中分配的内存
void Delete(struct SEQUENCE& L) { // 参数一:顺序表的引用
if (L.memory) { // 判断指针是否有内存,有,则释放;无,则跳过
delete[] L.memory;
L.length = 0; // 记得也要讲长度设为0
}
}
如下图:
打印顺序表的结果
根据项目的实际情况定夺。
// 打印输出结果
void print(struct SEQUENCE& L) {
cout << "顺序表的长度为:" << L.length << ", 内存大小为:" << L.size << endl;
for (int i = 0; i < L.length; i++) {
cout << L.memory[i] << ", ";
}
cout << endl;
}
测试代码:
#include <iostream>
#include <Windows.h>
using namespace std;
#define MAX_SIZE 100
struct SEQUENCE {
int* memory; // 首地址
int length; // 大小/元素个数
int size; // 内存大小
};
// 初始化
bool initSEQUENCE(struct SEQUENCE& L) {
L.memory = new int[MAX_SIZE]; // 分配内存
if (!L.memory) { // 判断是否分配失败
return false;
}
L.length = 0; // 空表长度为0
L.size = MAX_SIZE; // 顺序表的总空间大小
return true;
}
// 尾部插入数据
bool insertSEQUENCE(struct SEQUENCE& L, int e) { // 参数一:顺序表的引用; 参数二:需要插入的元素
if (L.length == L.size) return false; // 合法性检查,如果顺序表已满,则无法插入
L.memory[L.length] = e; // 将元素插入下标为length的位置
L.length++; // 顺序表的长度加1
return true;
}
// 中间插入数据
bool insert(struct SEQUENCE& L, int i, int e) { // 参数一:顺序表的引用;参数二:插入位置(下标);参数三:插入元素
if (i < 0 || i >= L.length) return false; // 合法性检查,中间插入元素,插入位置i不可能大于等当前元素的长度length
if (L.length == L.size) return false; // 合法性检查,如果顺序表已满,则无法插入
for (int j = L.length - 1; j >= i; j--) { // 把元素都往后移动一个位置,直到遇到插入位置为止
L.memory[j+1] = L.memory[j];
}
L.memory[i] = e; // 赋值需要插入的元素到下标i的位置
L.length++; // 顺序表的长度加1
return true;
}
// 元素删除
bool deleteSEQUENCE(struct SEQUENCE& L, int i) { // 参数一:顺序表的引用;参数二:删除位置(下标)
if (i < 0 || i >= L.length) return false; // 合法性检查,删除的元素,位置(下标)i不可能大于等当前元素的长度length
if (i == L.length - 1) { // 删除最后一个元素
L.length--; // 只需要将length长度减一即可
return true;
}
for (int j = i; j < L.length - 1; j++) { // 删除中间某个元素
L.memory[j] = L.memory[j + 1]; // 删除位置的后续元素往前移
}
L.length--; // length长度减一
return true;
}
// 释放顺序表中分配的内存
void Delete(struct SEQUENCE& L) { // 参数一:顺序表的引用
if (L.memory) { // 判断指针是否有内存,有,则释放;无,则跳过
delete[] L.memory;
L.length = 0; // 记得也要讲长度设为0
}
}
// 打印输出结果
void print(struct SEQUENCE& L) {
cout << "顺序表的长度为:" << L.length << ", 内存大小为:" << L.size << endl;
for (int i = 0; i < L.length; i++) {
cout << L.memory[i] << ", ";
}
cout << endl;
}
int main(void) {
struct SEQUENCE sequence;
// 初始化
cout << "正在初始化顺序表。。。" << endl;
if (initSEQUENCE(sequence)) {
cout << "顺序表初始化成功!" << endl;
} else {
cout << "顺序表初始化失败!" << endl;
return -1;
}
// 尾部插入元素
for (int i = 0; i < 5; i++) {
if (insertSEQUENCE(sequence, i)) {
cout << "插入成功!" << endl;
} else {
cout << "插入失败!" << endl;
}
}
print(sequence);
// 中间插入元素
if (insert(sequence, 4, 10)) {
cout << "插入成功!" << endl;
} else {
cout << "插入失败!" << endl;
}
print(sequence);
// 删除元素
if (deleteSEQUENCE(sequence, 5)) {
cout << "删除成功!" << endl;
} else {
cout << "删除失败!" << endl;
}
print(sequence);
// 销毁顺序表
Delete(sequence);
print(sequence);
system("pause");
return 0;
}
运行截图:
顺序表项目实战
使用顺序表实现浪漫星空,且星星慢慢移动退出屏幕。
效果:
下面是实现代码:
star.h头文件
#pragma once
#ifndef _STAR_H_
#define _STAR_H_
#define WINDOWS_X 840
#define WINDOWS_Y 600
#define STAR_SCORE 100 // 星星个数
#define RADII 3 // 随机半径
#define COLOUR 6 // 颜色系数
enum STATE {
PAUSE, //
UP, // 上
DOWN, // 下
LEFT, // 左
RIGHT, // 右
CONST, // 个数
};
struct STAR {
int starX;
int starY;
int radii; // 半径
int colour; // 颜色
int step; // 颜色系数和跳跃间隔
STATE state; // 星星状态
};
struct SEQUENCE {
struct STAR* memory; // 首地址
int length; // 大小/元素个数
int size; // 内存大小
};
// 顺序表的接口
bool initSEQUENCE(struct SEQUENCE& L);
bool insertSEQUENCE(struct SEQUENCE& L, struct STAR e);
bool deleteSEQUENCE(struct SEQUENCE& L, int i);
void Delete(struct SEQUENCE& L);
void print(struct SEQUENCE& L);
#endif
实现结构体接口:starSEQUENCE.cpp
#include <iostream>
#include "star.h"
using namespace std;
// 初始化
bool initSEQUENCE(struct SEQUENCE& L) {
L.memory = new struct STAR[STAR_SCORE];
if (!L.memory) {
return false;
}
L.length = 0;
L.size = STAR_SCORE;
return true;
}
// 尾部插入数据
bool insertSEQUENCE(struct SEQUENCE& L, struct STAR e) {
if (L.length == L.size) return false;
L.memory[L.length] = e;
L.length++;
return true;
}
// 元素删除
bool deleteSEQUENCE(struct SEQUENCE& L, int i) {
if (i < 0 || i >= L.length) return false;
if (i == L.length - 1) { // 删除最后一个元素
L.length--;
return true;
}
for (int j = i; j < L.length - 1; j++) { // 删除中间某个元素
L.memory[j] = L.memory[j + 1]; // 删除位置的后续元素往前移
}
L.length--;
return true;
}
void Delete(struct SEQUENCE& L) {
if (L.memory) {
delete[] L.memory;
L.length = 0;
}
}
// 打印输出结果
void print(struct SEQUENCE& L) {
cout << "顺序表的长度为:" << L.length << ", 内存大小为:" << L.size << endl;
for (int i = 0; i < L.length; i++) {
cout << "第" << i + 1 << "颗星星: x = " << L.memory[i].starX << ", y = " << L.memory[i].starY <<
"半径 = " << L.memory[i].radii << endl;
}
cout << endl;
}
mian函数实现
#include <graphics.h>
#include <iostream>
#include <Windows.h>
#include <cstdlib>
#include <ctime>
#include "star.h"
using namespace std;
// 星星的初始化
void initStar(struct STAR &_star) {
int rgb = 0;
_star.state = UP;
_star.starX = rand() % WINDOWS_X; // 0 - 839
_star.starY = rand() % (WINDOWS_Y - 100); // 0 - 499
_star.radii = rand() % RADII + 1; // 0 - 3
_star.step = rand() % COLOUR + 1;
rgb = 255 * _star.step / COLOUR;
_star.colour = RGB(rgb, rgb, rgb);
}
// 星星移动
void moveStar(struct SEQUENCE &star, int i) {
if (star.memory[i].state == PAUSE) return;
setfillcolor(RGB(0, 0, 0)); // 将星星擦除掉
solidcircle(star.memory[i].starX, star.memory[i].starY, star.memory[i].radii);
if (star.memory[i].state == UP) {
star.memory[i].starY -= star.memory[i].step;
if (star.memory[i].starY < 0) deleteSEQUENCE(star, i); // 判断如果星星超出范围,便删除
} else if (star.memory[i].state == DOWN) {
star.memory[i].starY += star.memory[i].step;
if (star.memory[i].starY > WINDOWS_Y) deleteSEQUENCE(star, i); // 判断如果星星超出范围,便删除
} else if (star.memory[i].state == LEFT) {
star.memory[i].starX -= star.memory[i].step;
if (star.memory[i].starX < 0) deleteSEQUENCE(star, i); // 判断如果星星超出范围,便删除
} else if (star.memory[i].state == RIGHT) {
star.memory[i].starX += star.memory[i].step;
if (star.memory[i].starX < WINDOWS_X) deleteSEQUENCE(star, i); // 判断如果星星超出范围,便删除
}
setfillcolor(star.memory[i].colour); // 将星星画上去
solidcircle(star.memory[i].starX, star.memory[i].starY, star.memory[i].radii);
}
int main(void) {
struct SEQUENCE star;
struct STAR _star;
// 初始化星星在顺序标中保存
initSEQUENCE(star);
initgraph(WINDOWS_X, WINDOWS_Y);
srand((unsigned int)time(NULL));
// 星星的初始化
for (int i = 0; i < STAR_SCORE; i++) {
initStar(_star);
insertSEQUENCE(star, _star);
}
// 画星星
for (int i = 0; i < star.length; i++) {
setfillcolor(star.memory[i].colour);
solidcircle(star.memory[i].starX, star.memory[i].starY, star.memory[i].radii);
}
//system("pause");
while (1) {
// 星星移动
for (int i = 0; i < star.length; i++) {
moveStar(star, i);
}
if (star.length == 0) {
break;
}
Sleep(50);
}
system("pause");
closegraph();
return 0;
}
顺序表总结:
顺序表可以说是一个数组,但是他比数组还要灵活。实现顺序表是使用结构体,顺序表的各种操作都是使用函数接口完成的。只需要设计好函数接口,顺序表还是很有用的!