数据结构--顺序表的增删查改--动态分配空间

一共有两份代码:

目录

第一份 分为 两个.c文件和一个.h文件

1、定义顺序表结构体和宏定义数据类型

2、顺序表的初始化

3、顺序表的摧毁(使用完需要摧毁顺序表)

4、顺序表元素的查找

5、检查ps的空间是否满了,如果满了则要重新分配空间

6、在pos位置插入数据

7、在pos位置删除数据

8、在头部插入数据

9、在头部删除数据

10、在尾部删除数据

11、在尾部插入数据

12、代码(全)

第二份 一个.c文件就可以运行


第一个分为 两个.c文件和一个.h文件

说明:

assert(ps)表示如果ps为空,会立即报错,使用这个函数一般要加头文件#include<assert.h>

ps表示SL类型的结构体,相当于顺序表

SeqList.h文件(头文件)存放函数的声明
SeqList.c文件(源文件)存放函数的定义
Seqtext.c存放主函数

1、定义顺序表结构体和宏定义数据类型

typedef int SLDateType;    //数据类型
typedef struct SeqList
{
	SLDateType* a;         //数据类型指针,指向动态开辟的数组
	int size;              //顺序表长度
	int capacity;          //顺序表容量
}SL;

2、顺序表的初始化



void SLInsert(SL* ps)     //顺序表的初始化
{
	assert(ps);

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

3、顺序表的摧毁(使用完需要摧毁顺序表)


void SLDestroy(SL* ps)  //顺序表的摧毁
{
	assert(ps);
	if (ps->a)          //如果ps->a不为空
	{
		free(ps->a);//释放掉pa->a空间
		ps->a = NULL;
		ps->size = ps->capacity = 0;
	}
}

4、顺序表元素的查找

int  SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

如果找到了需要找的值,返回值的下标,否者返回-1;

5、检查ps的空间是否满了,如果满了则要重新分配空间


void SLCheckCapacity(SL*ps)
{
	assert(ps);
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType *tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));//把新添加的用量添加到ps->a里面,这里注意tmp是地址空间
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newCapacity;
	}
}

刚开始初始化顺序表之后,也通过这个函数分配空间;在这里说一下realloc的作用:

 (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType))表示
给指向ps->a的指针分配一个大小为newCapacity * sizeof(SLDataType)大小
的空间,如果在原来指向ps->a的后面的空间被占用了,
则会异地开辟新的空间,
并且会拷贝原来的数据过来,而原来的空间会被释放掉。

6、在pos位置插入数据

//在pos 位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos>= 0);
	assert(pos <= ps->size);                               //此处可以等于0,因为在插入之前ps->a[size]的值为0

	SeqListCheckCapacity(ps);
	int end = ps->size-1;
	while (end>=pos)
	{
		ps->a[end+1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

在插入数据之前需要考虑顺序表容量有没有满:SEqListCheckCapacity(ps);如果没有满,则将在pos位置往后的数据往后挪,挪完之后再插入数据x;

7、在pos位置删除数据

//删除pos位置数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos < ps->size);
	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

8、在头部插入数据

void SLPushFront(SL* ps, SLDataType x)   //头插
{
	SLInsert(ps, 0, x);
}

9、在头部删除数据

void SLPopFront(SL* ps)   //头删
{
	SLErase(ps, 0);
}

10、在尾部删除数据


void SLPopBack(SL* ps)                   //尾删除
{
	SLErase(ps, ps->size-1);
}

11、在尾部插入数据

void SLPushBack(SL* ps, SLDataType x)           //尾插入
{
	SLInsert(ps, ps->size, x);
}

12、代码(全)

这个是.h文件(头文件),用来存放函数的声明和顺序表结构体的定义,引用头文件的时候记得加上#include"SeqList.h"

//SeqList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

//静态顺序表---不太实用
//N太小了不够用,N大了可能浪费
//#define  N 1000
//动态顺序表---按需扩空间
typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;            //记录存储多少个有效数据
	int capacity;        //空间容量大小
}SL;

void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);

void SLPrint(SL* ps);
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLCheckCapacity(SL* ps);    //检查容量

//尾插尾删
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);

//头插头删
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);

void menu();
int SLFind(SL* ps, SLDataType x, int begin);

 以下是SeqLIst.c文件,存放函数的定义

//SeqList.c
#define  _CRT_SECURE_NO_WARNINGS
#pragma once
#include"SeqList.h"

void SLCheckCapacity(SL*ps)
{
	assert(ps);
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType *tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));//把新添加的用量添加到ps->a里面,这里注意tmp是地址空间
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newCapacity;
	}
}

void SLPrint(SL* ps)     //打印
{
	assert(ps);
	for (int i = 0; i < ps->size; ++i)
	{
		printf(" %d", ps->a[i]);
	}
	printf("\n");
}

void SLInit(SL* ps)     //顺序表的初始化
{
	assert(ps);

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

void SLDestroy(SL* ps)  //顺序表的摧毁
{
	assert(ps);
	if (ps->a)          //如果ps->a有值在里面
	{
		free(ps->a);//释放掉pa->a空间
		ps->a = NULL;
		ps->size = ps->capacity = 0;
	}
}

//在pos位置插入数据
void SLInsert(SL *ps,int pos,SLDataType x)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos <= ps->size);

	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

//删除pos位置数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos < ps->size);
	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

void SLPushBack(SL* ps, SLDataType x)           //尾插入
{
	SLInsert(ps, ps->size, x);
}

void SLPopBack(SL* ps)                   //尾删除
{
	SLErase(ps, ps->size-1);
}
void SLPushFront(SL* ps, SLDataType x)   //头插
{
	SLInsert(ps, 0, x);
}

void SLPopFront(SL* ps)   //头删
{
	SLErase(ps, 0);
}

int  SLFind(SL* ps, SLDataType x, int begin)
{
	assert(ps);
	for (int i = begin; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

 以下是用来存放主函数的文件,以及一些函数的调用

//SLtest.c
#define  _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
void menu()
{
	printf("***********************************************************\n");
	printf("1、尾插数据 2、尾删数据\n");
	printf("3、头插数据 4、头删数据\n");
	printf("5打印数据  -1退出\n");
	printf("***********************************************************\n");
}
int main()
{
	SL ps;
	SLInit(&ps);             //顺序表的初始化
	//SLInsert(&ps,0,1);
	//SLPrint(&ps);
	int n=0;
	int option=0;
	do
	{
		menu();
		printf("输入操作\n");
		scanf("%d", &option);
		switch (option)
		{
		case 1: 
				printf("请输入你尾插的数据,以-1结束");
				scanf("%d",&n);
				while (n != -1)
				{
				SLPushBack(&ps,n);
				scanf("%d",&n);
				}
				break;
		case 2:
				SLPopBack(&ps);
				break;
		case 3:
				printf("请输入你头插入的数据,以-1结束\n");
				scanf("%d", &n);
				while (n != -1)
				{
				SLPushFront(&ps,n);
				scanf("%d", &n);
				}
				break;
		case 4:
				SLPopFront(&ps);
				break;
		case 5:
				SLPrint(&ps);
				break;
		default:
				break;
		}
	} while (option != -1);
	printf("????\n");
	SLDestroy(&ps);
	return 0;
}

第二份 一个.c文件就可以运行

(将代码复制到.c文件就可以运行)

#define  _CRT_SECURE_NO_WARNINGS
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;
	int capacity;
}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, int pos, SLDateType x);
// 顺序表删除pos位置的值

void SeqListInit(SeqList* ps)//初始化
{
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

void SeqListDestroy(SeqList* ps)
{
	assert(ps);
	if (ps->a)
	{
		free(ps->a);
		ps->a = NULL;               //指针制空,释放
		ps->size = ps->capacity = 0;
	}
}

void SeqPrint(SeqList* ps)          //打印
{
	int i;
	assert(ps);
	for (i = 0; i < ps->size; i++)
	{
		printf(" %d", ps->a[i]);
	}
}
void SeqListCheckCapacity(SeqList* ps)          //给ps->a 分配空间或者添加空间
{
	assert(ps);
	if (ps->size == ps->capacity)              //当顺序表长度等于顺序表的容量的时候
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDateType* temp = (SLDateType*)realloc(ps->a, newCapacity * sizeof(SLDateType));
		if (temp == NULL)                       //if里面用的是"=="
		{
			printf("realloc failed");
			exit(-1);
		}
		ps->a = temp;
		ps->capacity = newCapacity;
	}

}

//在pos位置删除数据
void SeqListErase(SeqList* ps, int pos)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos < ps->size);

	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin--] = ps->a[begin];        //pos位置的数据被它后一位的数据覆盖
		begin++;
	}
	ps->size--;
}
//在pos 位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos>= 0);
	assert(pos <= ps->size);                               //此处可以等于0,因为在插入之前ps->a[size]的值为0

	SeqListCheckCapacity(ps);
	int end = ps->size-1;
	while (end>=pos)
	{
		ps->a[end+1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}
void SeqListPushBack(SeqList* ps,SLDateType x)       //尾插
{
	SeqListInsert(ps, ps->size, x); //相当于在位置ps->a[size]处插入值x
}
void SeqListPopBack(SeqList* ps)                    //尾删
{
	SeqListErase(ps, ps->size - 1);//相当于在位置ps->a[size-1]处删除数据
}
void SeqListPushFront(SeqList* ps, SLDateType x)   //头插
{
	SeqListInsert(ps, 0, x);
}
void SeqListPopFront(SeqList* ps)                  //头删
{
	SeqListErase(ps, 0);
}
int SeqListFind(SeqList* ps, SLDateType x)         //查找元素
{
	assert(ps);
	for (int i = 0; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			return i;   //返回下标
		}
	}
	return -1; //若返回-1则找不到
}

int main()
{
	SeqList ps;
	int op;
	int x;
	int find;
	SeqListInit(&ps);                             //初始化
	do
	{
		printf("\n1、尾插 2、尾删 3、头插 4、头删 5、查找元素下标 6、打印 -1、退出\n");
		printf("输入你的操作:\n");
		scanf("%d", &op);
		switch (op)
		{
		case 1:
			printf("请输入你尾删的数据,以-1结束\n");
			scanf("%d", &x);
			while (x != -1)
			{
				SeqListPushBack(&ps, x);
				scanf("%d", &x);
			}
			break;
		case 2:
			SeqListPopBack(&ps); break;
		case 3:
			printf("请输入你头插的数据,以-1结束\n");
			scanf("%d", &x);
			while (x != -1)
			{
				SeqListPushFront(&ps, x);
				scanf("%d", &x);
			}
			break;
		case 4:
			SeqListPopFront(&ps); break;
		case 5:
			printf("请输入你要查找的元素x=");
			scanf("%d", &x);
			if ((find = SeqListFind(&ps, x)) == -1)
			{
				printf("没有该元素\n");
			}
			else
				printf("下标为%d", SeqListFind(&ps,x));
			break;
		case 6:
			SeqPrint(&ps); break;
		default:
			break;
		}
	} while (op != -1);
	
	SeqListDestroy(&ps);
	return 0;
}

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@简单就好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值