大家好呀!👋这个是付青云同学的博客,是一名大一在校生哦!😁😁
目前一直在学习C语言。🐸
写博客是为了来记录我的学习过程,同时也希望通过博客能够帮助到需要帮助的人。
如果我的博客可以帮助到你,不妨给我一个关注哦😁
顺序表
声明部分
我创建了一个头文件(fu.h)来声明
#pragma once
#define N 1000
typedef int SLDataType;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
//静态顺序表;
//typedef struct SeqList
//{
// SLDataType a[N];
// int size;//表示数组中存储了多少数据
//}SL;
//静态特点:如果满了就不让插入
//缺点:给多少很难确定
//动态顺序表;
typedef struct SeqList
{
SLDataType* a;
int size;//表示数组中存储了多少数据
int capacity;//数组实际能存数据的空间容量是多大
}SL;
//打印
void SeqListPrint(SL* ps);
//内存释放
void SeqListDestory(SL* ps);
//扩容
void SeqListCheckCapacity(SL* ps);
//接口函数 -- 命名风格是跟着STL走的
//初始化
void SeqListPushInit(SL* ps);
//从末尾插入一个
void SeqListPushBack(SL* ps, SLDataType x);
//从最末尾删除一个
void SeqListPopBack(SL* ps);
//从最前面插入一个
void SeqListPushFront(SL* ps, SLDataType x);
//从最前面删除一个
void SeqListPopFront(SL* ps);
//找到了返回x位置下标,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x);
//指定pos下标位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x);
//删除pos位置的数据
void SeqListErase(SL* ps, int pos);
以上就是顺序表要实现的基本功能的函数声明
现在我们就一一实现吧!
函数部分
#define _CRT_SECURE_NO_WARNINGS
#include "fu.h"
//打印
void SeqListPrint(SL* ps)
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
//内存释放
void SeqListDestory(SL* ps)
{
free(ps->a);
ps->a = NULL;
ps->capacity = ps->size = 0;
}
//初始化
void SeqListPushInit(SL* ps)
{
ps->a = NULL;
ps->capacity = 0;
ps->size = 0;
}
//扩容
void SeqListCheckCapacity(SL* ps)
{
//如果没有空间或者空间不足,则扩容
if (ps->size == ps->capacity)//扩容一般扩两倍
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = realloc(ps->a, sizeof(SLDataType) * newcapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);//程序异常退出,直接退出程序
}
ps->a = tmp;
ps->capacity = newcapacity;
}
}
//尾插
void SeqListPushBack(SL* ps, SLDataType x)
{
/*SeqListCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;*/
SeqListInsert(ps, ps->size, x);
}
//尾删
void SeqListPopBack(SL* ps)
{
///*if (ps->size > 0)
//{
// ps->size--;
//}*/
//assert(ps->size > 0);
//ps->size--;
SeqListErase(ps, ps->size - 1);
}
//头插
void SeqListPushFront(SL* ps, SLDataType x)
{
//SeqListCheckCapacity(ps);
挪动数据
//int end = ps->size - 1;
//while (end >= 0)
//{
// ps->a[end + 1] = ps->a[end];
// end--;
//}
//ps->a[0] = x;
//ps->size++;
SeqListInsert(ps, 0, x);
}
//尾插
void SeqListPopFront(SL* ps)
{
//assert(ps->size > 0);
///*int begin = 0;
//while (begin < ps->size - 1)
//{
// ps->a[begin] = ps->a[begin + 1];
// begin++;
//}*/
//int begin = 1;
//while (begin < ps->size)
//{
// ps->a[begin - 1] = ps->a[begin];
// begin++;
//}
//ps->size--;
SeqListErase(ps, 0);
}
//查找
int SeqListFind(SL* ps, SLDataType x)
{
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
//指定位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x)
{
/*if(pos > ps->size || pos < 0);
{
printf("pos invalid\n");
return;
}*/
assert(pos <= ps->size && pos >= 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 SeqListErase(SL* ps, int pos)
{
while (pos <= ps->size - 1)
{
ps->a[pos] = ps->a[pos + 1];
pos++;
}
ps->size--;
}
之后可以自行调用函数来测试顺序表
总结
写完这个顺序表发现它还是有缺点的:
- 空间不够了需要增容,而增容是要付出代价的;
- 所以避免频繁扩容,满了基本都是扩容两倍,但这样就可能导致一定的空间浪费;
- 顺序表要求数据从开始位置连续存储,那么我们在头部还在中间位置插入删除数据就需要挪动数据,效率不高。
当然,顺序表也是有优点的:它支持随机访问,可以使用像二分法、快排等算法来排序