数据结构——顺序表

顺序表

一.概念:

顺序表就是用一段连续的物理内存来存储数据的一种数据结构。一般情况下采用数组来存储。

二.基于顺序表的操作:

1.它的结构是怎样的?

现在假装小编画的矩形框都是等大的(每一个框就代表一个存储单元)。

2.顺序表的结构体:

typedef struct SList
{
	int *arr;		//记录动态数组的大小
	int size;		//记录顺序表有效元素的个数
	int capacity;
}SList;

3.其上的基本操作:增、删、改、查。

(1)先说增:增加的时候要考虑顺序表档期那是否已经为满,未满就正常增加,满了就得扩容了。

接下来就是要扩容的情况了:

(2)删除:

①按照值删除:

    a.只删除第一次遇到这个数的时候

        遍历顺序表,找到该数字,将它后面的数字全部向前移动一格即可

    b.删除所有遇到的该数字

       新建一个顺序表,遍历原顺序表,让非目标数字都转移到新的顺序表中来。

②按照下标删除:直接访问下标,将该下标后的数据全部向前移动一格。

(3)改:

①按照数值改:遍历顺序表,找到目标数字,重新为其赋值即可。

②按照下标改:直接通过下标访问,修改其中的值即可。

(4)查找元素:

    遍历整个顺序表即可,如果顺序表有序,我们可以采取二分查找法提高查找效率

三.代码实现

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//顺序表的增、删、改、查
typedef struct SList
{
	int *arr;		//记录动态数组的大小
	int size;		//记录顺序表有效元素的个数
	int capacity;
}SList;

//扩容
void SListExpand(SList* list)
{
	//扩容的条件:size=capacity
	if (list->size >= list->capacity)
	{
		//先分配一个比原来大两倍的内存空间来存放新的顺序表
		int Newcapacity = list->capacity * 2;
		int *Newarr = (int *)malloc(sizeof(int)*Newcapacity);
		//开始转移数据
		for (int i = 0; i < list->size; i++)
		{
			Newarr[i] = list->arr[i];
		}
		free(list->arr);
		list->arr = Newarr;
		list->capacity = Newcapacity;
	}
	printf("%d\n", list->capacity);
	return;
}


//初始化顺序表:将有效元素的个数置空
void SListInit(SList *list,int capacity)
{
	//将容量为capacity的顺序表进行初始化操作:
	//先分配内存
	//即将有效元素的个数置0
	list->arr = (int *)malloc(sizeof(int)*capacity);
	assert(list->arr != NULL);
	list->size = 0;
	list->capacity = capacity;
	return;
}
//插入:头插
void SListInsertFront(SList *list,int value)
{
	//先将元素进行后移,再进行插入操作
	for (int i = list->size; i > 0; i--)
	{
		list->arr[i] = list->arr[i - 1];
	}
	list->arr[0] = value;
	list->size++;
	return;
}
//尾插
void SListInsertTail(SList *list, int value)
{
	//不用搬运元素,直接进行赋值即可
	list->arr[list->size] = value;
	list->size++;
	return;
}
//在指定位置pos处插入
void SListInsert(SList *list, int pos, int value)
{
	//将pos后的元素全部向后移动一格
	for (int i = list->size; i > pos; i--)
	{
		list->arr[i] = list->arr[i - 1];
	}
	list->arr[pos] = value;
	list->size++;
	return;
}

//删除:头删
void SListDeleteFront(SList *list)
{
	//将所有的元素前移一个位置即可
	for (int i = 0; i < list->size; i++)
	{
		list->arr[i] = list->arr[i + 1];
	}
	list->size--;
	return;
}

//尾删
void SListDeleteTail(SList *list)
{
	list->size--;
	return;
}

//在指定位置pos处删除
void SListDelete(SList *list, int pos)
{
	//将pos位置后的元素都向前移动一个位置即可
	for (int i = pos; i < list->size; i++)
	{
		list->arr[i] = list->arr[i + 1];
	}
	list->size--;
	return;
}


//查找某一个值:遍历顺序表
int* SListFindvalue(SList *list, int value)
{
	//
	int i,j;
	int *count = (int *)malloc(sizeof(int)*list->size);		//用来记录已查到目标数字的下标
	for (i = 0,j = 0; i < list->size; ++i) {
		if (list->arr[i] == value) {
			count[j] = i;
			printf("找到该数,下标是:%d  \n", count[j]);			
			++j;
		}
		else if (i >= list->size) {
			free(count);		//如果查无此数,就释放用来记录下标的数组的空间
			count = NULL;		//并且让其指向空
			printf("未找到该数!!!\n");
			return NULL;
		}
	}
}

//删除顺序表中的某一个值:只删除第一次遇到该数的时候
void SListDeletevalue(SList *list, int value)
{
	//先查询此数
	int* findvalue = SListFindvalue(&list, value);
	if (findvalue == NULL)
	{
		printf("查无此数,无法删除!!!\n");
	}
	else if (findvalue != NULL)
	{
		//开始进行删除操作:只删除第一个
		SListDelete(&list, findvalue[0]);
	}
	return;
}


//销毁
void SListDestory(SList *list)
{
	free(list->arr);
	list->arr == NULL;
	list->size = 0;
	list->capacity = 0;
	
	printf("销毁顺序表!\n");
	return;
}


//输出顺序表
void SListPrint(SList *list)
{
	if (list->arr == NULL)
	{
		printf("顺序表为空!!!\n");
		return;
	}

	for (int i = 0; i < list->size; i++)
	{
		printf("%-3d", list->arr[i]);
	}
	printf("\n");
	return;
}



int main()
{
	SList list;
	SListInit(&list,10);			//初始化
	SListInsertFront(&list,10);		//头插
	SListInsertFront(&list, 10);		//头插

	SListInsertTail(&list, 20);		//尾插
	SListInsert(&list, 1, 30);		//指定位置插入
	SListPrint(&list);				//打印顺序表
	SListExpand(&list);
	SListFindvalue(&list, 10);

	//SListDeleteFront(&list);		//头删
	//SListDeleteTail(&list);			//尾删
	SListDelete(&list, 1);			//指定位置删除

	//SListDestory(&list);			//销毁
	SListPrint(&list);				//打印顺序表
	system("pause");
	return 0;
}

四.总结

1.通过上面的操作,我们不难看出,对顺序表的核心操作增删改查其实也就是对数组的操作

2.优点:随即下标访问时间复杂度O(1)——快到飞起!

3.缺点:

①会有一定程度上的空间浪费

②删除操作要搬运数据:如果频繁操作,就得拼命搬运数据,效率大大降低

它与链表的区别也就在这了,

小编随笔:

链表:我用起来比你灵活。

顺序表:我查起来比你快!

链表:我插入删除超级方便。

顺序表:我查起来比你快!

链表:。。。

顺序表:我查起来比你快!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值