顺序表(C语言版)

顺序表是线性表的一种,顺序表分为静态顺序表和动态顺序表。

顺序表定义(静态与动态)

静态顺序表:以定长数组储存元素

#define N 7
typedef int SLDateType;//将int类型重新起一个别名SLDataType
typedef struct SeqList
{
	SLDateType a[N];//定长数组有效的元素
	size_t size;//有效的元素个数
	size_t capacity; // unsigned int无符号整型
}SeqList;

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

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;//指向动态开辟的数组
	size_t size;//有效元素个数
	size_t capacity; // 顺序表的容量
}SeqList;

顺序表初始化

void SeqListInit(SeqList* ps)//传入的变量为 顺序表结构体
{
	assert(ps);//此处为断言
	ps->a = (SLDateType*)malloc(10 * sizeof(SLDateType));//动态申请顺序表空间
	if (NULL == ps->a)
	{
		printf("申请空间失败......\n");
		exit(0);//若申请失败则退出
	}
	ps->size = 0;//初始化有效元素个数为0
	ps->capacity = 10;//初始化顺序表容量为10
}

其中malloc函数的头文件为  #include<stdlib.h>

malloc函数的默认返回值是void*,我们在使用时需要强转为我们所需要的(SLDataType*)

(10 * sizeof(SLDataType))代表的是我们申请了10个SLDataType类型大小的空间

而assert(ps)断言的作用是检测空指针,如果传入的ps指针是空指针,则退出程序

assert()的头文件是 #include <assert.h>

exit(0)的头文件是 #include <stdlib.h>

顺序表销毁

void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	if (ps->a != NULL)
	{
		free(ps->a);
		ps->a = NULL;//free之后需要手动将指针置为NULL,防止内存泄漏
		ps->size = 0;//顺序表销毁之后有效元素为0
		ps->capacity = 0;//顺序表销毁之后顺序表容量为0
	}
}

free()函数的作用是对动态分配的内存进行释放,但是free函数只是将参数指针指向的内存归还给操作系统,并不会把参数指针置为NULL,为了以后访问到被操作系统重新分配后的错误数据,所以在调用free之后,通常需要手动将指针置NULL。

顺序表打印

void SeqListPrint(SeqList* ps)
{
	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d",ps->a[i]);
	}
	printf("\n");
}

顺序表尾插

void SeqListPushBack(SeqList* ps, SLDateType x)
{
	assert(ps);
	
	ps->a[ps->size] = x;
	ps->size++;
}

顺序表头插

void SeqListPushFront(SeqList* ps, SLDateType x)
{
	assert(ps);
	for (int i = ps->size-1; i >= 0; --i)
	{
		ps->a[i + 1] = ps->a[i];//顺序表中所有元素向后搬移
	}
	ps->a[0] = x;
	ps->size++;
}

顺序表头删

void SeqListPopFront(SeqList* ps)
{
	for (int i = 0; i < ps->size; ++i)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

顺序表尾删

void SeqListPopBack(SeqList* ps)
{
	ps->size--;
}

顺序表查找

// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			printf("%d\n", i);
			return i;
		}
	}
	//如果x不在顺序表中
	return -1;
}

顺序表在pos位置之后插入x

void SeqListInsert(SeqList* ps, size_t pos, SLDateType x)
{
	assert(ps);
	if (pos > ps->size)
	{
		printf("参数越界了。。。。。\n");
		exit(0);
	}
	for (int i = ps->size - 1; i >= pos; --i)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;
}

顺序表删除pos位置之后的值

void SeqListErase(SeqList* ps, size_t pos)
{
	assert(ps);
	if (pos > ps->size)
	{
		printf("参数越界了。。。。。\n");
		exit(0);
	}
	for (int i = pos + 1; i < ps->size; ++i)//将pos以及之后的所有元素整体向前搬移一个单位
	{
		ps->a[i - 1] = ps->a[i];//a[i-1]才是pos位置的元素
	}
	ps->size--;
}

判断顺序表是否为空

size_t SeqListEmpty(SeqList* ps)
{
	assert(ps);
	return 0 == ps->size;//若为空则返回true,不为空则返回false
}

全部代码:

utili.h

#pragma once

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	size_t size;
	size_t capacity; // unsigned int
}SeqList;

// 对数据的管理:增删查改 
void SeqListInit(SeqList* ps);
void SeqListDestroy(SeqList* ps);

void SeqListPrint(SeqList* ps);
void SeqListPushBack(SeqList* ps, SLDateType x);
void SeqListPushFront(SeqList* ps, SLDateType x);
void SeqListPopFront(SeqList* ps);
void SeqListPopBack(SeqList* ps);

// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置之后插入x
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x);
// 顺序表删除pos位置之后的值
void SeqListErase(SeqList* ps, size_t pos);
//顺序表是否为空
size_t SeqListEmpty(SeqList* ps);

顺序表.c

#include "utili.h"
//顺序表初始化
void SeqListInit(SeqList* ps)
{
	assert(ps);
	ps->a = (SLDateType*)malloc(10 * sizeof(SLDateType));
	if (NULL == ps->a)
	{
		printf("申请空间失败......\n");
		exit(0);
	}
	ps->size = 0;
	ps->capacity = 10;
}
//顺序表销毁
void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	if (ps->a != NULL)
	{
		free(ps->a);
		ps->a = NULL;
		ps->size = 0;
		ps->capacity = 0;
	}
}
//顺序表打印
void SeqListPrint(SeqList* ps)
{
	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d",ps->a[i]);
	}
	printf("\n");
}
//顺序表尾插
void SeqListPushBack(SeqList* ps, SLDateType x)
{
	assert(ps);
	
	ps->a[ps->size] = x;
	ps->size++;
}
//顺序表头插
void SeqListPushFront(SeqList* ps, SLDateType x)
{
	assert(ps);
	for (int i = ps->size-1; i >= 0; --i)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;
	ps->size++;
}
//顺序表头删
void SeqListPopFront(SeqList* ps)
{
	for (int i = 0; i < ps->size; ++i)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}
//顺序表尾删
void SeqListPopBack(SeqList* ps)
{
	ps->size--;
}
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			printf("%d\n", i);
			return i;
		}
	}
	//如果x不在顺序表中
	return -1;
}
// 顺序表在pos位置之后插入x
void SeqListInsert(SeqList* ps, size_t pos, SLDateType x)
{
	assert(ps);
	if (pos > ps->size)
	{
		printf("参数越界了。。。。。\n");
		exit(0);
	}
	for (int i = ps->size - 1; i >= pos; --i)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;
}
// 顺序表删除pos位置之后的值
void SeqListErase(SeqList* ps, size_t pos)
{
	assert(ps);
	if (pos > ps->size)
	{
		printf("参数越界了。。。。。\n");
		exit(0);
	}
	for (int i = pos + 1; i < ps->size; ++i)
	{
		ps->a[i - 1] = ps->a[i];
	}
	ps->size--;
}
//判断顺序表是否为空
size_t SeqListEmpty(SeqList* ps)
{
	assert(ps);
	return 0 == ps->size;
}

测试代码部分:

#include "utili.h"
int main()
{
	SeqList s = {NULL,0,0};//定义一个顺序表
	SeqListInit(&s);//顺序表初始化
	SeqListPushBack(&s, 1);//尾插一个元素 1
	SeqListPushBack(&s, 2);//尾插一个元素 2
	SeqListPushBack(&s, 3);//尾插一个元素 3
	SeqListPushBack(&s, 4);//尾插一个元素 4
	SeqListPushBack(&s, 5);//尾插一个元素 5
	SeqListPrint(&s);//打印此时的顺序表

	SeqListPushBack(&s,6);//尾插一个元素 6
	SeqListPrint(&s);//打印此时的顺序表

	SeqListPushFront(&s,0);//头插一个元素 0
	SeqListPrint(&s);//打印此时的顺序表

	SeqListPopFront(&s);//删除第一个元素 0
	SeqListPrint(&s);//打印此时的顺序表

	SeqListPopBack(&s);//删除最后一个元素 6
	SeqListPrint(&s);//打印此时的顺序表

    SeqListFind(&s,1);//查找元素1,并返回其所在的下标

	SeqListInsert(&s,3,6);//在第三个位置后插入新元素6(下标为3的位置)
	SeqListPrint(&s);//打印此时的顺序表

    SeqListErase(&s,1);//删除第一个位置之后的元素(下标为1)
	SeqListPrint(&s);//打印此时的顺序表

	SeqListDestroy(&s);//销毁顺序表
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值