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;
}

順序表總結:
順序表可以說是一個數組,但是他比數組還要靈活。實現順序表是使用結構體,順序表的各種操作都是使用函數接口完成的。只需要設計好函數接口,順序表還是很有用的!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章