数据结构顺序表(C语言)

前言:

 线性表的介绍:

        线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
        线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储

顺序表:

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

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

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

介绍顺序表的创建与销毁:

第一步:

创建顺序表,初始化顺序表。

第二步:

进行顺序表的头插或尾插(如果空间不够,先开辟空间,后进行插入

第三步:

可以实现删除,查找等功能,具体实现在下文有详细说明,最后释放掉开辟的空间,防止内存泄漏!

注:该篇重点介绍静态顺序表!

    为了方便展示更加详细的顺序表的建立使用过程,我将建立三个文件

分别是:

test.c文件(测试文件)

seqlist.c文件(函数的定义)

seqlist.h文件(函数的声明,结构体的定义)

静态顺序表的定义:

定义结构体:

        在test.h头文件中定义结构体:

#include<stdio.h>
#include<stdlib.h>
#define  SLDataType int
typedef struct Seqlist//typedef类型重定义
{
	SLDataType* a;
	int size;//记录元素的个数
	int capacity;//记录开辟空间的总个数
}SL;

        这里由于不知道顺序表中元素的类型,所以定义一个常量,如果需要更改,可以直接改SLDtatType!!

初始化顺序表:

        由于结构体前面只是做了一个定义,并没有进行初始化,现在进行结构体的初始化:

在test.c中定义结构体变量:

#include"seqlist.h"
int main()
{
	SL s1;//定义结构体变量
//相当于struct Seqlist s1
	return 0;
}

seqlist.c中初始化结构体变量:

目的

        1、将指针指向NULL

        2、将顺序表的容量置为0

        3、将顺序表的指向个数置为0

注意事项:

        1、在传参的时候必须传入变量的地址,用指针接收,如果只是传入变量本身,形参只是实参的临时拷贝!!

#include"seqlist.h"
void SLInit(SL* s1)
{
	s1->a = NULL;
	s1->capacity = 0;
	s1->size = 0;
}

顺序表的尾插:

        首先检查空间够不够,不够用要开辟空间,接着进行尾插操作。

void SLPushBack(SL* s1, SLDataType x)
{
	if (s1->size == s1->capacity)
	{
		int newcapacity = s1->size > 0 ? s1->size * 2:4;
		SLDataType* tmp = malloc(newcapacity*sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("SLPushBack :: malloc");
			exit(-1);
		}
		s1->a = tmp;
		s1->capacity = newcapacity;
	}
	s1->a[s1->size] = x;
	s1->size++;
}

        为了后续写其他函数时,也要进行空间的检查,所以这里空间的检查可以封装成一个函数,在需要的时候进行调用!!
        
       

void CheckCapacity(SL* s1)
{
	if (s1->size == s1->capacity)
	{
		int newcapacity = s1->size > 0 ? s1->size * 2 : 4;
		SLDataType* tmp = malloc(newcapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("SLPushBack :: malloc");
			exit(-1);
		}
		s1->a = tmp;
		s1->capacity = newcapacity;
	}
}

    改造后变为:

void SLPushBack(SL* s1, SLDataType x)
{
	CheckCapacity(s1);
	s1->a[s1->size] = x;
	s1->size++;
}

顺序表的头插:

        如图解读:

假设此时对该顺序表进行头插。

第一步:将所有元素向后覆盖!

第二部:在第一个位置插入元素。

代码如下:

void SLPushFront(SL* s1, SLDataType x)
{
	CheckCapacity(s1);
	int num = s1->size;
	while (num)
	{
		s1->a[num] = s1->a[num - 1];
		num--;
	}
	s1->a[0] = x;
	s1->size++;
}

顺序表的尾删:


  需要注意的点:

1、尾删的个数不能为0.

2、尾删传过来的指针不能为空。

3、尾删需要将个数减一。

代码如下:

void SLPopBack(SL* s1)
{
	assert(s1);
	assert(s1->size > 0);
	s1->size--;
}

顺序表的头删:

    需要注意的点:

1、头删的个数不能为0.

2、头删传过来的指针不能为空。

3、采用覆盖删除,而且必须是从前往后覆盖!

4、头删需要将个数减一。

代码如下:

void SLPopFront(SL* s1)
{
	assert(s1);
	assert(s1->size > 0);
	int i = 0;
	for (i = 0; i < s1->size-1; i++)
	{
		s1->a[i] = s1->a[i + 1];
	}
	s1->size--;
}

综合插入(想往哪放就往哪放):

        前面介绍了头插和尾插,为了方便我们可以想往哪放就往哪放。

这时候就需要传入三个参数,分别是

1、顺序表地址

2、想要插入的位置

3、想要插入的数字

代码如下:

void Insert(SL* s1, int pos, SLDataType x)
{
	CheckCapacity(s1);
	assert(s1);
	assert(pos-1>=0 && pos-1<=s1->size);
	int num = s1->size ;
	while (num >= pos-1)
	{
		s1->a[num+1] = s1->a[num];
		num--;
	}
	s1->a[pos - 1] = x;
	s1->size++;
}

综合删除(想删哪里就删哪里):

注意事项:
1、删除时不能传空指针。

2、删除的位置必须在size的范围内

3、删除方式为覆盖删除,覆盖的次数必须要清楚。

代码如下:

void Earse(SL* s1, int pos)
{
	assert(s1);
	assert(pos-1>= 0 && pos-1< s1->size);
	int num = pos-1;
	for (num = pos-1; num < s1->size; num++)
	{
		s1->a[num+1] = s1->a[num];
	}
	s1->size--;
}

空间的释放:

void SLDestroy(SL* s1)
{
	assert(s1);
	if (s1->a != NULL)
	{
		free(s1->a);
		s1->a = NULL;
		s1->capacity = 0;
		s1->size = 0;
	}
}

 

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
顺序表是一种线性表,它的物理存储结构是连续的。在 C 语言中,可以用数组来实现顺序表。以下是一个简单的顺序表的 C 语言实现: ```c #include <stdio.h> #define MAXSIZE 100 // 定义顺序表的最大长度 typedef struct { int data[MAXSIZE]; // 存储数据元素的数组 int length; // 当前顺序表的长度 } SeqList; // 初始化顺序表 void InitList(SeqList *L) { L->length = 0; } // 获取顺序表中指定位置的元素 int GetElem(SeqList L, int i) { if (i < 1 || i > L.length) { printf("Error: index out of range.\n"); return -1; } return L.data[i-1]; } // 在顺序表中插入元素 void ListInsert(SeqList *L, int i, int e) { int j; if (L->length == MAXSIZE) { printf("Error: list is full.\n"); return; } if (i < 1 || i > L->length+1) { printf("Error: index out of range.\n"); return; } for (j = L->length; j >= i; j--) { L->data[j] = L->data[j-1]; } L->data[i-1] = e; L->length++; } // 删除顺序表中指定位置的元素 void ListDelete(SeqList *L, int i) { int j; if (i < 1 || i > L->length) { printf("Error: index out of range.\n"); return; } for (j = i; j < L->length; j++) { L->data[j-1] = L->data[j]; } L->length--; } // 输出顺序表中的元素 void PrintList(SeqList L) { int i; for (i = 0; i < L.length; i++) { printf("%d ", L.data[i]); } printf("\n"); } int main() { SeqList L; InitList(&L); ListInsert(&L, 1, 1); ListInsert(&L, 2, 2); ListInsert(&L, 3, 3); ListInsert(&L, 4, 4); ListInsert(&L, 5, 5); PrintList(L); ListDelete(&L, 3); PrintList(L); printf("%d\n", GetElem(L, 2)); return 0; } ``` 在这个例子中,我们定义了一个结构体 `SeqList`,其中包含一个数组 `data` 和一个表示顺序表长度的变量 `length`。然后我们定义了一些操作函数来对顺序表进行初始化、插入、删除、获取元素和输出顺序表的元素。在 `main()` 函数中,我们创建了一个顺序表 `L`,并对它进行了一些操作,最后输出了结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值