C++ 入门算法,你必须懂的“顺序表”

顺序表简介:
顺序表是简单的一种线性结构,他们可以说是连续存储元素的,也可以称之为数组。顺序表可以快速定位到第几个元素的位置,中间不允许有空值。插入、删除时需要移动大量的元素!

顺序表的三个要素:

  1. 用elems记录存储位置的基地址;
  2. 分配一段连续的存储空间size;
  3. 用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;
}

顺序表总结:
顺序表可以说是一个数组,但是他比数组还要灵活。实现顺序表是使用结构体,顺序表的各种操作都是使用函数接口完成的。只需要设计好函数接口,顺序表还是很有用的!

发布了47 篇原创文章 · 获赞 37 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/cpp_learner/article/details/104833889
今日推荐