C语言之 数据结构入门——顺序表的构造

一、顺序表是什么?

  • -谈论顺序表前,谈谈线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

  • 顺序表是数据结构的线性表的其中一小类,线性表是指n个具有相同性质的数据元素的有限序列

  • 顺序表(SeqList):顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构(连续存储数据,不能跳跃)。

在这里插入图片描述


二、构建顺序表的结构体

2.1静态和动态顺序表

静态顺序表:

#define N 100
typedef int SLDataType;
typedef struct Seqlist {
	int arr[N];  //定义数组的长度
	int size; //数组元素个数
}sl;

动态顺序表:

typedef int data;

typedef struct Seqlist {
	data* a;//指向动态开辟的数组
	int size; //数组元素的个数
	int capacity;//数组的长度
}sl;

结构体的定义是必不可少的,一般都是采用动态顺序表 ,更好调整顺序表的大小。接下来也是根据动态顺序表来讲述。


三.构造顺序表的函数接口

3.1功能要求

函数接口是实现功能必不可少的环节,将需要实现的功能先放在.h头文件里

//初始化顺序表
void seqlistinit(sl* ps);
//扩容顺序表
void CheckCapacity(sl* ps);
//顺序表的尾插
void seqlistpushback(sl* ps,data x);
//顺序表的尾删
void seqlistpopback(sl* ps);
//顺序表的头插
void seqlistpushfront(sl* ps,data x);
//顺序表的头删
void seqlistpopfront(sl* ps);
//查找顺序表对应值的下标
int seqlistfind(sl* ps, data x);
//打印顺序表结果
void seqlistprintf(sl* ps);
//删除某个节点
void seqlistdetel(sl* ps, data x);
//插入x元素到y节点前
void seqlistinsert(sl* ps, data x, data y);

3.2功能实现

现在讲解以上各部分的接口实现代码

3.2.1初始化顺序表

顺序表的初始化很简单,添加了断言,是为了防止彻底进来的指针为空。

void seqlistinit(sl* ps)
{
	assert(psl != NULL);  //断言
	ps->a = NULL;//初始化顺序表为空
	ps->capacity = ps->size = 0;//数组长度和元素为0
}

3.2.2扩容顺序表

顺序表被初始化后没有元素,也没有容积,而且当数组元素满了之后都是需要给顺序表扩容,使它可以继续存放数据。

void CheckCapacity(sl* ps)
{
  if (ps->capacity == ps->size)
	  {
	  //判断容积是空的还是满的
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		data* tmp = (data*)realloc(ps->p, newcapacity * sizeof(data));
		ps->a = tmp;
		ps->capacity = newcapacity;
	  }
}

3.2.3顺序表的打印

顺序表肯定是需要打印的,需要将结果呈现出来

void seqlistprintf(sl* ps)
{
	assert(ps != NULL);  //断言

	if (ps->size == 0)  //判断顺序表是否为空
	{
		printf("顺序表为空\n");
		return;
	}
	int i = 0;
	while (i < ps->size)
	{
		printf("%2d", ps->p[i]);
		i++;
	}
}

3.2.4顺序表的尾插

尾插:在顺序表的后端插入一个元素。需要检查空间足够的情况下。

void seqlistpushback(sl* ps, data x)
{
	assert(ps != NULL);
	CheckCapacity(ps);//检查空间是否足够,是否进行扩容
	ps->p[ps->size] = x;
	ps->size++;
}

3.2.5顺序表的尾删

就是将顺序表的最后一个元素删除

void seqlistpopback(sl* ps)
{
    assert(ps != NULL);
    if(ps->size!=0)
	ps->size--; //就是将有效元素减一
}

3.2.6顺序表的头插

头插需要将一个元素插入数组的最前面,与此同时,后面的所有元素需要向后移动一位

void seqlistpushfront(sl* ps,data x)
{
	assert(ps != NULL);  //断言
	CheckCapacity(ps);//检查空间是否足够,是否进行扩容
    int m = ps->size-1;
	for(m;m<=0;m--)
	{
		ps->p[m + 1] = ps->p[m];
		
	}
	ps->p[0] = x;
	ps->size++;
}

3.2.7查找元素,返回位置

利用size,将元素从尾到前找起,找到了返回下标,没找到返回-1;

int seqlistfind(sl* ps, data x)
{
    assert(ps != NULL);  //断言
	int y = 1;
	int m = ps->size - 1;
	int z = m+1;
	while(z)
	{
		if (ps->p[m] == x)break;
		else y = 0;
		m--; z--;
	}
	return m; //m为元素的下标位置,若是m=-1,则元素不存在
}

3.2.8删除顺序表的某个下标位置数据

在该下标,后面的数据向前移动一位,进行替换。

void seqlistdetel(sl* ps, data x)
{
    assert(ps != NULL);  //断言
	int y = ps->size;
	while (x < y)
	{
		ps->p[x - 1] = ps->p[x];
		x++;
	}
	ps->size--;//有效数字减一
}

3.2.9插入一个元素到指定下标位置前

先判断容积是否满了,是否需要进行扩容,然后找到该下标元素将该下标之后的所有元素进行向后移动一位
,在进行在自己需要的位置上插入元素

void seqlistinsert(sl* ps, data x, data y)
{
	assert(ps != NULL);  //断言
	CheckCapacity(ps);//检查空间是否足够,是否进行扩容
	int w = ps->size - 1;
	while (w >= x)
	{
		ps->p[w + 1] = ps->p[w];
		w--;
	}
	ps->p[x] = y;//将目标的位置进行赋值
	ps->size++;//有效数字加一;
}

4.构造顺序表所需要的库函数

#include<stdio.h>
#include"malloc.h"
#include"assert.h"

5.代码全篇

#include<stdio.h>
#include"malloc.h"
#include"assert.h"
typedef int data;

typedef struct Seqlist {
	data* a;//指向动态开辟的数组
	int size; //数组元素的个数
	int capacity;//数组的长度
}sl;
void seqlistinit(sl* ps)
{
	assert(psl != NULL);  //断言
	ps->a = NULL;//初始化顺序表为空
	ps->capacity = ps->size = 0;//数组长度和元素为0
}
void CheckCapacity(sl* ps)
{
  if (ps->capacity == ps->size)
	  {
	  //判断容积是空的还是满的
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		data* tmp = (data*)realloc(ps->p, newcapacity * sizeof(data));
		ps->a = tmp;
		ps->capacity = newcapacity;
	  }
}
void seqlistprintf(sl* ps)
{
	assert(ps != NULL);  //断言

	if (ps->size == 0)  //判断顺序表是否为空
	{
		printf("顺序表为空\n");
		return;
	}
	int i = 0;
	while (i < ps->size)
	{
		printf("%2d", ps->p[i]);
		i++;
	}
}
void seqlistpushback(sl* ps, data x)
{
	assert(ps != NULL);
	CheckCapacity(ps);//检查空间是否足够,是否进行扩容
	ps->p[ps->size] = x;
	ps->size++;
}
void seqlistpopback(sl* ps)
{
    assert(ps != NULL);
    if(ps->size!=0)
	ps->size--; //就是将有效元素减一
}
void seqlistpushfront(sl* ps,data x)
{
	assert(ps != NULL);  //断言
	CheckCapacity(ps);//检查空间是否足够,是否进行扩容
    int m = ps->size-1;
	for(m;m<=0;m--)
	{
		ps->p[m + 1] = ps->p[m];
		
	}
	ps->p[0] = x;
	ps->size++;
}
void seqlistdetel(sl* ps, data x)
{
    assert(ps != NULL);  //断言
	int y = ps->size;
	while (x < y)
	{
		ps->p[x - 1] = ps->p[x];
		x++;
	}
	ps->size--;//有效数字减一
}
void seqlistinsert(sl* ps, data x, data y)
{
	assert(ps != NULL);  //断言
	CheckCapacity(ps);//检查空间是否足够,是否进行扩容
	int w = ps->size - 1;
	while (w >= x)
	{
		ps->p[w + 1] = ps->p[w];
		w--;
	}
	ps->p[x] = y;//将目标的位置进行赋值
	ps->size++;//有效数字加一;
}
void Text()
{
	sl c;
	seqlistinit(&c);  //初始化
	seqlistpushback(&c, 4);   //尾插一个数4
	seqlistpushback(&c, 5);  //尾插一个数5
	seqlistpushback(&c, 9);  //尾插一个数9
	seqlistpushback(&c, 8); //尾插一个数8
	seqlistpushback(&c, 1); //尾插一个数1
    seqlistpopback(&c);     //尾删一个数----1
	seqlistpushfront(&c, 999);//头插一个数----999
	seqlistdetel(&c, 2);   //删除下标为2的数字
	seqlistinsert(&c, 2, 3);  //在下标为3的位置前插入一个2
	seqlistprintf(&c);         //打印顺序表
    printf("\n%d",seqlistfind(&c, 999));   //查找999的下标位置

}

int main()
{
	Text();
	return 0;
}

注:顺序表是线性表中可谓是最简单的一种,各位努力学习的IT人员们,还得一起加油努力哦。祝各位学业有成,财源滚滚。