顺序表的增删查改

2.1概念及结构

顺序表是用一段 物理地址连续 的存储单元依次存储数据元素的线性结构,一般情况下采用数组存
储。在数组上完成数据的增删查改。
顺序表一般可以分为:

1. 静态顺序表:使用定长数组存储元素

//静态顺序表
#define MAX 1000

typedef int SLDataType;

typedef struct SeqList 
{
	SLDataType a[MAX];  //储存有效数据
	size_t size;		//有效数据的个数

}SL;
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致 N 定大了,空
间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间
大小,所以能够按需分配的动态顺序表就产生了

2. 动态顺序表:使用动态开辟的数组存储。

2.2 接口实现

下面我们实现动态顺序表。
typedef int SLDataType;
// 顺序表的动态存储
typedef struct SeqList
{
 SLDataType* array;  // 指向动态开辟的数组
 size_t size ;       // 有效数据个数
 size_t capicity ;   // 容量空间的大小
}SeqList;

顺序表的基本使用可以大致分为以下四个部分。

1.操作顺序表的整体

(1)顺序表的初始化

// 顺序表初始化
void SeqListInit(SeqList* ps)
{
//函数接收到指针一定断言来判断是否有空指针,之后不再提醒
	assert(ps);

	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

(2)顺序表的销毁

void SeqListDestory(SeqList* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
        //free之后一定要置空,养成好的代码习惯喔
	ps->size = ps->capacity = 0;
}

(3)顺序表的打印

void SeqListPrint(SeqList* ps)
{
	assert(ps);

	for (size_t i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->a[i]);
	}

	printf("%\n");

(4)检查顺序表的容量

此处在添加一点realloc函数的使用

relloc函数的作用是

  更改 所指向的内存块的大小。
该函数可以将内存块移动到新位置(函数返回其地址)。


注意:内存块的内容将保留到新旧大小中较小的一个,即使将块移动到新位置也是如此。如果新值较大,则新分配部分的值不确定。
如果这是空指针,则该函数的行为类似于 分配一个新的字节块并返回指向其开头的指针

使用案例

/* realloc example: rememb-o-matic */
#include       /* printf, scanf, puts */
#include      /* realloc, free, exit, NULL */

int main ()
{
  int input,n;
  int count = 0;
  int* numbers = NULL;
  int* more_numbers = NULL;

  do {
     printf ("Enter an integer value (0 to end): ");
     scanf ("%d", &input);
     count++;

     more_numbers = (int*) realloc (numbers, count * sizeof(int));

     if (more_numbers!=NULL) {
       numbers=more_numbers;
       numbers[count-1]=input;
     }
     else {
       free (numbers);
       puts ("Error (re)allocating memory");
       exit (1);
     }
  } while (input!=0);

  printf ("Numbers entered: ");
  for (n=0;n

2.顺序表的头部操作

顺序表的头部插入数据

// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x)
{
	//1.检查容量
	CheckCapacity(psl);

	//按顺序挪动数据
	for (int end = psl->size - 1;end >= 0;end--)
	{
		psl->a[end + 1] = psl->a[end];
	}
	psl->a[0] = x;
	psl->size++;
}

删除顺序表头部的数据             

                        ——其实就是用第一个数据之后的元素依次覆盖,只是要特别注意一下避免越界

// 顺序表头删
void SeqListPopFront(SeqList* psl)
{
	//1.
	for (int start = 0;start < psl->size - 1;start++)
	{
		psl->a[start] = psl->a[start + 1];
	}
	
	//2.
	for (int start = 1;start < psl->size ;start++)
	{
		psl->a[start-1] = psl->a[start ];
	}

	psl->size--;
}

3操作顺序表的尾部

尾插和尾删

// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x)
{
	//1.检查容量
	CheckCapacity(psl);//插入操作都要检查容量

	//2.插入数据
	psl->a[psl->size] = x;
	psl->size++;


}
// 顺序表尾删
void SeqListPopBack(SeqList* psl)
{
	//1.检查顺序表是否为空
	if (0 == psl->size)
	{
		printf("顺序表为空表\n");
		return;
	}
	else
	{
		psl->size--;
		//要删除的那个数据不用特意去设置,系统会给一个随机值覆盖。

	}
}

4.对指定位置的操作

(1.)查找


// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x)
{
	assert(psl);
	for (int i = 0;i< psl->size;i++)
	{
		if (psl->a[i] == x)
			return i;
	}
	return -1;//没找到
}

(2.)在指定位置插入数据


// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x)
{
	assert(psl);
	assert(pos <= psl->size);

	//先将pos之后的数据依次后移
	size_t end = psl->size;
	while (end > pos)
	{
		psl->a[end] = psl->a[end - 1];
		--end;
	}

	//将数据插入到pos位置
	psl->a[pos] = x;
	psl->size++;


}

(3.)删除指定位置的数据


// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos)
{
	assert(psl);
	assert(pos <= psl->size);

	//也要注意不要越界访问

	//1.方案1
	for (int began = pos;began < psl->size - 1;began++)
	{
		psl->a[began] = psl->a[began + 1];
	}

	//2. 方案2
	for (int began = pos+1;began <= psl->size - 1;began++)
	{
		psl->a[began-1] = psl->a[began];
	}


	psl->size--;
}

以上就是我对顺序表的基本操作的一些粗略理解,欢迎各位大佬斧正。

你可能感兴趣的:(笔记,c语言,开发语言,数据结构)