c++实现顺序表的基本操作

本文详细介绍了顺序表的实现,包括动态分配存储空间的线性表结构,以及一系列基本操作如初始化、销毁、清空、判断是否为空、获取长度、获取元素、插入元素、删除元素等。此外,还展示了合并两个非递减有序线性表的方法。代码中使用了模板,方便处理不同类型的数据,并提供了用户交互界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

顺序表

数组描述方法将元素存储在一个数组中,用一个数学公式来确定每个元素存储的位置,即在数组中的索引。这是最简单的一种存储方式,所有元素依次存储在一片连续的存储空间中,这就是通常所说的顺序表。   ---   数据结构、算法与应用 


顺序表的实现

 线性表动态分配顺序存储结构

ps:为了方便修改数据元素的类型,使用了模板,可以方便修改线性表中的数据元素的类型;

#define LIST_INIT_SIZE 100     // 线性表存储空间的初始分配量

#define LISTNCREMENT 10        // 线性表存储空间的分配增量

template <class T>
struct SeqList
{
	T* element;        // 存储空间的基质
	int capacity;      // 线性表的当前分配的存储容量
	int listSize;;     // 线性表的当前长度
};

顺序表的基本操作 

void initMenu();            // 初始化菜单
SeqList<int>* initList();             // 初始化线性表
bool distroyList(SeqList<int>*&);     // 销毁线性表
bool clearList(SeqList<int>*&);       // 清空线性表
bool isEmpty(SeqList<int>*&);         // 判断是否为空
int getLength(SeqList<int>*&);        // 得到线性表的当前长度
int getElement(SeqList<int>*&, int);            // 得到指定位置的元素
int getIndex(SeqList<int>*&, int);              // 得到元素的下标
int getPreElement(SeqList<int>*&, int);         // 得到元素的前驱
int getSeqElement(SeqList<int>*&, int);         // 得到元素的后继
bool insertElement(SeqList<int>*&, int, int);   // 插入元素
bool deleteElement(SeqList<int>*&, int);        // 删除元素
void showElement(SeqList<int>*&);               // 遍历表中的所有元素
void megerList(SeqList<int>*&, SeqList<int>*&); // 合并两个线性表

自定义函数的实现

void initMenu()    // 初始化菜单界面
{
    cout << "*************************" << endl;
    cout << "1---初始化线性表" << endl;
    cout << "2---销毁线性表" << endl;
    cout << "3---清空线性表" << endl;
    cout << "4---判断线性表是否为空" << endl;
    cout << "5---求线性表的长度" << endl;
    cout << "6---获取线性表中指定位置的元素" << endl;
    cout << "7---获取线性表元素的位置" << endl;
    cout << "8---求前驱" << endl;
    cout << "9---求后继" << endl;
    cout << "10---在线性表指定位置插入元素" << endl;
    cout << "11---删除线性表指定位置的元素" << endl;
    cout << "12---显示线性表" << endl;
    cout << "13---合并两个非递减有序的线性表" << endl;
    cout << "14---退出程序(输入负数)" << endl;
    cout << "*************************" << endl;
}

(1)线性表的初始化

初始化线性表,是指初始化一个空的线性表,里面的元素个数是0 

SeqList<int>* initList()        // 初始化线性表
{
	SeqList<int>* MyList = new SeqList<int>();
	try
	{
		MyList->element = new int[LIST_INIT_SIZE];
		MyList->capacity = LIST_INIT_SIZE;
		MyList->listSize = 0;
	}
	catch (bad_alloc)
	{
		cerr << "初始化失败!" << endl;
		exit(1);
	}

	cout << "初始化成功!" << endl;
	return MyList;
}

(2)销毁线性表 、清空线性表、判断是否为空、返回线性表的长度

销毁线性表:释放线性表的基地址,将capacity与listSize赋值为0

清空线性表:只需将listSize赋值为0

判断是否为空:只需判断listSize的值是否为0

返回线性表的长度:只需将listSize的值返回

bool distroyList(SeqList<int>*& arrayList)    // 销毁线性表

{
	bool isDistory = false;
	delete arrayList->element;
	arrayList->element = nullptr;
	arrayList->capacity = 0;
	arrayList->listSize = 0;
	if (arrayList->element == nullptr)
	{
		isDistory = true;
	}
	return isDistory;
}

bool clearList(SeqList<int>*& arrayList)    // 清空线性表
{
	bool isClear = false;
	arrayList->listSize = 0;
	if (arrayList->listSize == 0)
	{
		isClear = true;
	}
	return isClear;
}

bool isEmpty(SeqList<int>*& arrayList)    // 判断线性表是否为空
{
	if (arrayList->listSize > 0)
	{
		return false;
	}
	return true;
}

int getLength(SeqList<int>*& arrayList)    // 得到线性表的当前长度
{
	return arrayList->listSize;
}

(3)获得对应位置的元素 

int getElement(SeqList<int>*& arrayList, int index)     // 得到对应位置的元素
{
	if (index > arrayList->listSize || index < 0)       // 判断用户输入的下标是否合法
	{
		return -1;
	}
	return arrayList->element[index - 1];
}

(4)获得线性表元素的下标 

int getIndex(SeqList<int>*& arrayList, int num)    // 得到元素的下标
{
	for (int i = 0; i < arrayList->listSize; i++)
	{
		if (arrayList->element[i] == num)
		{
			return i;
		}
	}
	return -1;
}

(5)获得前驱 

遍历顺序表找到与用户输入元素相同的元素的下标,将该下标-1得到前驱,但要注意特殊情况即当该元素为第一个元素时,没有前驱。

int getPreElement(SeqList<int>*& arrayList, int num)     // 得到元素的前驱
{
	int temp = -2;    // 用来记录元素前驱的下标
	for (int i = 0; i < arrayList->listSize; i++)
	{
		if (arrayList->element[i] == num && i == 0)
		{// 顺序表的第一个元素,没有前驱
			return -1;
		}
		if (arrayList->element[i] == num)
		{// 找到前驱
			temp = i - 1;
			break;
		}
	}
	if (temp == -2)
	{// 没有该元素
		return -2;
	}
	return arrayList->element[temp];
}

(6)获得后继

遍历顺序表找到与用户输入元素相同的元素的下标,将该下标+1得到后继,但要注意特殊情况即当该元素为最后一个元素时,没有后继。 

int getSeqElement(SeqList<int>*& arrayList, int num)    // 得到元素的后继
{    
	int temp = -2;     // 用来记录元素前驱的下标
	for (int i = 0; i < arrayList->listSize; i++)
	{
		if (arrayList->element[i] == num && i == arrayList->listSize - 1)
		{// 顺序表的最后一个元素,没有后继
			return -1;
		}
		if (arrayList->element[i] == num)
		{// 找到后继
			temp = i + 1;
			break;
		}
	}
	if (temp == -2)
	{// 没有该元素
		return -2;
	}
	return arrayList->element[temp];
}

(7)插入元素

插入元素之前要判断线性表是否初始化(主函数中实现),插入的位置是否合法,顺序表是否已满。

在顺序表的第i个位置插入元素e,与数组的插入操作基本相同,将顺序表第i个位置之后的元素从后向前依次向后移动一个位置,然后将元素e插入第i个位置,在插入元素之后要将顺序表的当前长度listSize++,但要注意是从后往前依次移动元素,即:先移动最后一个元素,在移动倒数第二个元素,依次类推

bool insertElement(SeqList<int>*& arrayList, int index, int num)    // 插入元素
{
	if (index < 1 || index > arrayList->listSize + 1)    // 判断插入的位置是否合法
	{
		return false;
	}
	if (arrayList->listSize >= arrayList->capacity)    // 判断顺序表的空间是否已满
	{
		try
		{
			int* newbase = new int[LIST_INIT_SIZE + LISTNCREMENT];    // 重新分配新的空间
			copy(arrayList->element, arrayList->element + LIST_INIT_SIZE, newbase);    // 将顺序表的元素赋值给新的顺序表
			arrayList->element = newbase;
			arrayList->capacity += LISTNCREMENT;
		}
		catch (bad_alloc)
		{
			exit(OVERFLOW);
		}
	}
	for (int i = arrayList->listSize - 1; i >= index - 1; i--)    // 插入操作,同数组的插入
	{
		arrayList->element[i + 1] = arrayList->element[i];
	}
	arrayList->element[index - 1] = num;
	arrayList->listSize++;
	return true;
}

(8)删除元素

删除元素之前要判断线性表是否初始化(主函数实现),顺序表是否为空(主函数实现),删除的位置是否合法。

删除线性表中的第i个元素,与数组的删除操作基本相同,需要将表中第i个元素之后的元素依次向前移动一位,将前面的元素覆盖。移动元素时要将第i+1个元素移动到第i个位置,在将第i+2个元素移动i+1的位置,直到将最后一个元素移动到它的前一个位置,删除元素之后,将顺序表的当前长的listSize--;

bool deleteElement(SeqList<int>*& arrayList, int index)     // 删除下表对应的元素

{
	if (index < 1 || index > arrayList->listSize)    // 判断用户输入的下标是否合法
	{
		return false;
	}

	for (int i = index - 1; i < arrayList->listSize; i++)    // 删除操作,同数组的删除
	{
		arrayList->element[i] = arrayList->element[i + 1];
	}
	arrayList->listSize--;
	return true;
}

(9)遍历线性表 

void showElement(SeqList<int>*& arrayList)    // 遍历线性表
{
	cout << "该线性表的元素为:" << endl;
	for (int i = 0; i < arrayList->listSize; i++)
	{
		cout << arrayList->element[i] << "\t";
	}
	cout << endl;
}

(10)合并两个非降序线性表

ps:该方法也是我自己在力扣上做题的时候学的,下面附上该方法的链接

画解算法:88. 合并两个有序数组

void megerList(SeqList<int>*& arrayList, SeqList<int>*& myList)    // 合并两个线性表
{    // myList 线性表在调用该函数前需要初始化,具体实现在主函数
	int size1 = arrayList->listSize;    // 记录arrayList的空间大小
	int size2 = myList->listSize;       // 记录myArray的空间大小
	int len1 = size1 - 1;               
	int len2 = size2 - 1;
	int len = size1 + size2 - 1;
    // 以上声明均为了更方便的实现一下操作

    // 合并两个非降序线性表前需要将两个线性表非降序排序
	sort(arrayList->element, arrayList->element + size1);
	sort(myList->element, myList->element + size2);

	SeqList<int>* newList = new SeqList<int>();    // 新的线性表,用来存储两个线性表合并后的新表
	newList->element = new int[size1 + size2]{ -1 };
	newList->listSize = size1 + size2;

	while (len1 >= 0 && len2 >= 0)    // 合并两个线性表的具体实现
	{
		newList->element[len--] = arrayList->element[len1] > myList->element[len2] ? arrayList->element[len1--] : myList->element[len2--];
	}

	if (len1 >= 0)
	{
		copy(arrayList->element, arrayList->element + (len1 + 1), newList->element);
	}
	if (len2 >= 0)
	{
		copy(myList->element, myList->element + (len2 + 1), newList->element);
	}

	cout << "合并后的顺序表为:" << endl;
	for (int i = 0; i < newList->listSize; i++)
	{
		cout << newList->element[i] << "\t";
	}
	cout << endl;
}

主函数的实现

int main()
{
	initMenu();
	SeqList<int>* arrayList = new SeqList<int>();

	int choice;
	cout << "请输入操作代码:";
	cin >> choice;

	while (choice > 0)
	{
		switch (choice)
		{
		case 1://初始化线性表空间
		{
			arrayList = initList();
			break;
		}
		case 2://销毁线性表
		{
			bool isTrue = distroyList(arrayList);
			if (isTrue)
			{
				cout << "销毁成功!" << endl;
			}
			else
			{
				cout << "销毁失败!" << endl;
				exit(1);
			}
			break;
		}
		case 3://清空线性表
		{
			bool isTrue = clearList(arrayList);
			if (isTrue)
			{
				cout << "清空成功!" << endl;
			}
			else
			{
				cout << "清空失败!" << endl;
				exit(1);
			}
			break;
		}
		case 4://判断线性表是否为空
		{
			bool isTrue = isEmpty(arrayList);
			if (isTrue)
			{
				cout << "该表为空" << endl;
			}
			else
			{
				cout << "该表不为空" << endl;
			}
			break;
		}
		case 5://求线性表的长度
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			cout << "线性表的长度为:" << getLength(arrayList) << endl;
			break;
		}
		case 6://获取线性表中指定位置的元素
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			if (isEmpty(arrayList))
			{
				cout << "请先为顺序表添加元素!" << endl;
				break;
			}
			int index;
			cout << "请输入要查找元素的位置:";
			cin >> index;
			int temp = getElement(arrayList, index);
			if (temp == -1)
			{
				cerr << "访问越界!" << endl;
			}
			else
			{
				cout << "该元素为:" << temp << endl;
			}
			break;
		}
		case 7://获取线性表元素的位置
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			if (isEmpty(arrayList))
			{
				cout << "请先为顺序表添加元素!" << endl;
				break;
			}
			int num;
			cout << "请输入您要查找的元素:";
			cin >> num;
			int temp = getIndex(arrayList, num);
			if (temp == -1)
			{
				cerr << "线性表中没有该元素!" << endl;
			}
			else
			{
				cout << "该元素的下标为:" << temp << endl;
			}
			break;
		}
		case 8://求前驱
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			if (isEmpty(arrayList))
			{
				cout << "请先为顺序表添加元素!" << endl;
				break;
			}
			int num;
			cout << "请输入求前驱的元素:";
			cin >> num;
			int temp = getPreElement(arrayList, num);
			if (temp == -1)
			{
				cout << "该元素没有前驱!" << endl;
			}
			else if (temp == -2)
			{
				cerr << "线性表中没有该元素!" << endl;
			}
			else
			{
				cout << "该元素的前驱为:" << temp << endl;
			}
			break;
		}
		case 9://求后继
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			if (isEmpty(arrayList))
			{
				cout << "请先为顺序表添加元素!" << endl;
				break;
			}
			int num;
			cout << "请输入求后继的元素:";
			cin >> num;
			int temp = getSeqElement(arrayList, num);
			if (temp == -1)
			{
				cout << "该元素没有后继!" << endl;
			}
			else if (temp == -2)
			{
				cerr << "线性表中没有该元素!" << endl;
			}
			else
			{
				cout << "该元素的后继为:" << temp << endl;
			}
			break;
		}
		case 10://在线性表指定位置插入元素
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			int index, num;
			cout << "请输入要插入的位置下标与元素(end of -1):";
			cin >> index >> num;
			while (index != -1)
			{
				bool isTrue = insertElement(arrayList, index, num);
				if (!isTrue)
				{
					cerr << "错误插入!" << endl;
					exit(1);
				}
				else
				{
					cout << "插入成功!" << endl;
					cout << "请输入要插入的位置下标与元素(end of -1):";
					cin >> index >> num;
				}
			}
			break;
		}
		case 11://删除线性表指定位置的元素
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			if (isEmpty(arrayList))
			{
				cout << "该顺序表已空!" << endl;
				break;
			}
			int index;
			cout << "请输入要删除的位置:";
			cin >> index;
			bool isTrue = deleteElement(arrayList, index);
			if (!isTrue)
			{
				cerr << "删除失败!" << endl;
				exit(1);
			}
			else
			{
				cout << "删除成功!" << endl;
			}
			{}
			break;
		}
		case 12://显示线性表
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			if (isEmpty(arrayList))
			{
				cout << "请先为顺序表添加元素!" << endl;
				break;
			}
			showElement(arrayList);
			break;
		}
		case 13://合并两个非递减有序的线性表
		{
			if (arrayList->element == nullptr)
			{
				cout << "请先初始化顺序表!" << endl;
				break;
			}
			if (isEmpty(arrayList))
			{
				cout << "请先为顺序表添加元素!" << endl;
				break;
			}
			cout << "自动创建一个新的线性表!" << endl;
			SeqList<int>* myList = initList();
			int index, num;
			cout << "请输入要插入的位置下标与元素(end of -1):";
			cin >> index >> num;
			while (index != -1)
			{
				insertElement(myList, index, num);
				cout << "请输入要插入的位置下标与元素(end of -1):";
				cin >> index >> num;
			}
			megerList(arrayList, myList);
			break;
		}
		default:
			break;
		}
		Sleep(1000);
		system("cls");
		initMenu();
		cout << "请输入操作代码:";
		cin >> choice;
	}
	cout << "程序退出!" << endl;
	return 0;
}

注:本人已测试过该代码,如要亲自测试该代码,请添加头文件

#include <iostream>
#include <algorithm>
#include <Windows.h>

最后:

本人是第一次发表文章,以上代码仅为个人写法,不喜勿喷,如有不足或错误的地方欢迎指正。如果文章对你有所帮助,欢迎点赞支持。欢迎转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值