顺序表

线性表和链表是数据结构中很重要的存储数据的结构,也是数据结构最基础的内容

一.顺序表(静态)

顺序表是用一段地址连续的存储单元依次存放数据元素的线性结构。地址连续的空间我们一般采用数组来表示,顺序表又分为静态顺序表和动态顺序表,静态顺序表只可存储固定数量的数据,而动态顺序表则可以通过在使用过程中的不断扩容来改变其容量的大小。
在这里插入图片描述
1.创建顺序表
创建一个顺序表需要一个存放数据的数组和一个标志其容量的数据,所以我们用一个结构体来将这两个元素构成一个顺序表的结构类型。

typedef int Datatype;				//为了适用于多种数据类型
#define MAX_SIZE 100
typedef struct Seqlist
{
	Datatype data[MAX_SIZE];
	int size;						//当前有效容量
}Seqlist;

2.初始化顺序表
初始化只需要将其有效容量size置为0即可。

void SeqlistInit(Seqlist *pSeqlist)
{
	assert(pSeqlist);
	pSeqlist->size = 0;
}

3.顺序表的头插
顺序表的头插比较麻烦,首先应该先判断该顺序表中有无元素,若有将新元素插入即可,可若有元素就必须先将表中的第一个位置空出来以便插入,就需要将所有元素向后挪动一格,这时候就有一个新的问题,如果表中元素已满无法向后挪动则这次头插失败。挪动的时候你要考虑挪动的顺序,一定是从当前表中最后一个有效元素开始挪动,否则会造成元素的丢失。

void SeqlistPushfront(Seqlist*pSeqlist, Datatype d)
{
	assert(pSeqlist);                //在对指针解引用之前必须判断它不为空,否则会越界访问
	if (pSeqlist->size == MAX_SIZE)  //判断顺序表是否已满
	{
		return;
	}
	int i = 0;
	for (i = pSeqlist->size; i > 0; i--)
	{
		pSeqlist->data[i] = pSeqlist->data[i - 1];
	}
	pSeqlist->data[0] = d;
	pSeqlist->size++;				//成功头插后,size+1
}

4.顺序表尾插
尾插相对于头插来说就简便了很多,不用牵扯原本表内有效元素的移动,只需要判断顺序表是否已满,未满则在下标为size的地方插入(因为以数组存储,当有size个元素时其下标为0~size-1)即可。

void SeqlistPushback(Seqlist*pSeqlist, Datatype d)
{
	assert(pSeqlist);                          //此处断言不可省略
	if (pSeqlist->size == MAX_SIZE)
	{
		return;
	}
	pSeqlist->data[pSeqlist->size] = d;
	pSeqlist->size++;
}

5.顺序表头删
顺序表的头删和头插一样是在如果表中有元素的情况下需要移动当前表中的元素,与头插不同的是移动的方向相反。在删除前需要判断表中是否有元素,若表中没有元素则无法完成删除

void SeqlistPopfront(Seqlist*pSeqlist)
{
	assert(pSeqlist);
	assert(pSeqlist->size > 0);
	int i = 0;
	for (; i <= pSeqlist->size - 2;i++)
	{
		pSeqlist->data[i] = pSeqlist->data[i + 1];
	}
	pSeqlist->size--;
}

6.顺序表尾删

void SeqlistPopback(Seqlist*pSeqlist)
{
	assert(pSeqlist);
	assert(pSeqlist->size > 0);
	pSeqlist->size--;
}

7.在指定位置前插入

void SeqlistInsert(Seqlist*pSeqlist, int pos, Datatype d)
{
	assert(pSeqlist);
	if (pSeqlist->size == MAX_SIZE)
	{
		return;
	}
	int i = 0;
	for (i = pSeqlist->size; i > pos; i--)
	{
		pSeqlist->data[i] = pSeqlist->data[i - 1];
	}
	pSeqlist->data[pos] = d;
	pSeqlist->size++;
}

8.查找指定元素,若有则返回下标,否则返回-1
查找元素就是从顺序表的第一个元素开始遍历该顺序表,依次比较其值与指定元素是否相等,相等则返回下标,否则指针+1判断下一个元素。若遍历完表中所有元素仍无与之匹配的则返回-1.

bool Find(const Seqlist *pSeqlist, Datatype d)
{
	int i = 0;
	for (i = 0; i < pSeqlist->size; i++)
	{
		if (pSeqlist->data[i] == d)
		{
			return i;
		}
	}
	return -1;
}

9.删除指定位置的元素
所有的删除都要判断顺序表是否非空

void SeqlistErase(Seqlist*pSeqlist, int pos)
{
	int i = 0;
	assert(pSeqlist);
	assert(pSeqlist->size > 0);
	assert(pos >= 0 && pos < pSeqlist->size);
	for (i = pos; i < pSeqlist->size -1; i++)
	{
		pSeqlist->data[i] = pSeqlist->data[i + 1];
	}
	pSeqlist->size--;
}

10.删除指定元素(若表中有多个只可删除第一个)
删除指定元素可以调用Find函数和Erase函数,先用Find函数查找该元素,若有则接受其在顺序表的下标,调用Erase删除即可。

void SeqlistRemove(Seqlist*pSeqlist, Datatype d)
{
	int i = 0;
	assert(pSeqlist && pSeqlist->size>0);
	int pos = Find(pSeqlist, d);
	if (pos == -1)
	{
		return;
	}
	SeqlistErase(pSeqlist, pos);
}

11.删除指定所有元素
通过新建数组,把不等于 data 的数据 copy 到 extra

void RemoveAll(Seqlist *pSeqlist, Datatype d)
{
	int i = 0;
	int j = 0;
	assert(pSeqlist && pSeqlist->size > 0);
	for (; i < pSeqlist->size; i++) 
	{
		if (pSeqlist->data[i] != d) 
		{
			pSeqlist->data[j++] = pSeqlist->data[i];
		}
	}
	pSeqlist->size = j;
}

12.顺序表的判空,判满以及查看当前有效元素个数
<1>判空
不为空则返回当前有效size大小。

bool SeqlistEmpty(const Seqlist*pSeqlist)
{
	return pSeqlist->size;
}

<2>判满
返回与MAX_SIZE是否相等

bool Full(const Seqlist*pSeqlist)
{
	return pSeqlist->size==MAX_SIZE;
}

<3>当前有效元素个数

int SeqlistSize(const Seqlist*pSeqlist)
{
	return pSeqlist->size;
}

13.对顺序表中的元素进行冒泡排序
为了方便后面的冒泡排序首先写了swap函数用以交换两个数的值,代码如下

void swap(Datatype *s1,Datatype *s2)				//一般进行交换是尽量传地址交换
{
	Datatype tmp;
	tmp = *s1;
	*s1 = *s2;
	*s2 = tmp;
}

以下是冒泡排序的程序,同普通的冒泡排序一样,两层循环遍历依次排序。

void BubbleSort(Seqlist *pSeqlist)
{
	int i = 0;
	int j = 0;
	int flag = 0;            //为了尽量的减少时间复杂度,尽量少做无用功
	for (i = 0; i < pSeqlist->size - 1; i++)
	{
		for (j = 0; j < pSeqlist->size - i - 1; j++)
		{
			if (pSeqlist->data[j]>pSeqlist->data[j + 1])
			{
				swap(pSeqlist->data+j, pSeqlist->data+j + 1);
				flag = 1;
			}
		}
		if (flag = 0)
		{
			break;
		}
	}
}

14.打印顺序表
依次遍历并打印其data值即可。

void SeqlistShow(Seqlist*pSeqlist)
{
	int i = 0;
	for (i = 0; i < pSeqlist->size; i++)
	{
		printf("%d ", pSeqlist->data[i]);
	}
	printf("\n");
}

15.销毁顺序表
销毁和初始化一样只需要将其size置0即可。

void SeqlistDestroy(Seqlist *pSeqlist)
{
	assert(pSeqlist);
	pSeqlist->size = 0;
}
使用c++实现的顺序表:多文件编程,层次清晰,函数有注释 SeqList();//构造函数,存储的元素个数设为0 bool setLength(size_t length);//设置已经存储的元素个数 bool addElement(ElemType element);//把某个元素添加到顺序表末尾 bool addElement(ElemType element , size_t n);//插入一个元素,使其成为第n个元素,其余元素后移 bool delElement();//删除所有的元素 bool delElement(size_t n);//删除第n个元素 bool delElement(string elementDetailType,string elementDetail);//通过某个元素细节找到元素,把这个元素删除 bool replaceElement(ElemType element , size_t n);//使用一个元素,替换掉第n个元素 bool swapElement(size_t n1 , size_t n2);//把第n1个元素和第n2个元素交换 ElemType* getElement();//得到数组头的指针 ElemType* getElement(size_t n);//得到第n个元素的指针 size_t getLength();//得到存储的元素个数 size_t getMaxSize();//得到顺序表容量 bool showElementDetail();//输出所有的元素细节 bool showElementDetail(size_t n);//输出第n个元素的细节 bool showElementDetail(string elementDetailType,string elementDetail);//通过某个元素细节找到元素,输出元素所有细节 size_t findElement(string elementDetailType,string elementDetail);//通过某个元素细节找到元素位置 static int inputAInt(int min = 0,int max = 9,int defaultValue = -1);//从键盘读取,限制为一个min到max间的整数,非法情况返回defaultValue void startControlLoop();//打开控制界面 ~SeqList();//析构函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值