写在前面
大家好我是消失了不止两周半的还在学习编程的一个人,前段时间刚好晚上有时间,还去打打篮球,也有练习弹吉他和唱歌,看了好多的唱歌技巧教学视频,还是过的蛮充实的。但还是要坚持学习,以后的梦想就是有钱了之后去植发,做街上最亮的崽。好了言归正传,整理一下之前的顺序表相关内容:
顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组 上完成数据的增删查改
顺序表一般可以分为:
- 静态顺序表:使用定长数组存储。
- 动态顺序表:使用动态开辟的数组存储
当然如果使用静态的顺序表的话肯定会比较鸡肋了,因此我们实现一下动态的顺序表;
头文件:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
typedef struct SeqList
{
DataType *_array;
size_t _size;
size_t _capacity;
}SeqList;
void SeqListInit(SeqList *ps);//初始化顺序表
void SeqListDestory(SeqList *ps);//删除顺序表
void SeqListCheckCapacity(SeqList*ps);//检查容量
void SeqListPushBack(SeqList *ps,DataType x);//尾插
void SeqListPushFront(SeqList *ps,DataType x);//头插
void SeqListPopBack(SeqList *ps);//尾删
void SeqListPopFront(SeqList *ps);//头删
void SeqListInsert(SeqList *ps,size_t pos,DataType x);//按位置插入
void SeqListErase(SeqList *ps,size_t pos);//按位置删除
size_t SeqListSize(SeqList *ps);//求大小
size_t SeqListFind(SeqList *ps,DataType x);//查找数据
DataType SeqListAt(SeqList *ps,size_t pos);//访问pos位置的值
这里我们看到有 #pragma once 它的主要作用以及意思如下:
1、编译器预编译命令
2、命令内容显而易见:仅编译一次
3、用途:常出现在头文件中。因为同一头文件会在许多源文件中多次引用。如果没有指定编译一次,则编译时出现重定义错误。
在这里另外讲一下 typedef 这个东东:
基本定义:typedef 为C语言的关键字,作用是为一种数据类型定义一个新名字,也就是大家常说的重命名。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
在编程中使用 typedef 目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
而它主要有什么作用呢?来看一下一段代码:
typedef int SLDataType;
typedef struct SListNode
{
SLDataType _data;
struct SListNode* _next;
}SListNode;
- 这里我们可以看到第一个 typedef 就是把 int 重命名为:SLDataType。 以后的 int 都用 SLDataType 来代替 ,这样做的一个好处就是如果要更改整个代码里的数据类型只用在 typedef 后更改,就可以更改所有的数据类型。
- 而第二个也就是把结构体 struct SListNode 重命名成 SListNode 这样就可以更加简洁,方便以后的使用,但是需要主义的是结构体内的 struct SListNode* _next;这里因为 typedef还没有生效,所以结构体内还是 struct SListNode*,当重定义之后 struct SListNode 就可以用 SListNode代替。
子函数:
#include "SeqList.h"
void SeqListInit(SeqList *ps)//初始化顺序表
{
assert(ps);
ps->_array=NULL;
ps->_capacity=0;
ps->_size=0;
}
void SeqListDestory(SeqList *ps)//删除顺序表
{
assert(ps);
if(ps->_array)
{
free(ps->_array);
ps->_array=NULL;//将数组置空即可
ps->_capacity=ps->_size=0;//置为零
}
}
void SeqListCheckCapacity(SeqList*ps)//检查是否需要增容
{
assert(ps);
if(ps->_capacity==ps->_size)
{
size_t newcapacity=(ps->_capacity== 0 ) ? 4 : ps->_capacity;
ps->_array=(DataType*)realloc(ps->_array,sizeof(DataType)*newcapacity);//开辟空间
ps->_capacity =newcapacity;
}
}
void SeqListPushBack(SeqList *ps,DataType x)//尾插
{
assert(ps);
SeqListCheckCapacity(ps);
ps->_array[ps->_size]=x;//将数据插到最后一个size++即可
ps->_size++;
}
void SeqListPushFront(SeqList *ps,DataType x)//头插
{
size_t end;
assert(ps);
SeqListCheckCapacity(ps);
end=ps->_size;
while(end>0)
{
ps->_array[end]=ps->_array[end-1];//实际上是将数据全部往后挪动一个位置,然后插入
--end;
}
ps->_array[0]=x;//把数据插入到第一个也就是数组的a[0]位置
ps->_size++;
}
void SeqListPopBack(SeqList *ps)//尾删
{
assert(ps && ps->_size>0);
ps->_array[ps->_size-1]=NULL;//将最后一个置空size--即可
--ps->_size;
}
void SeqListPopFront(SeqList *ps)//头删
{
size_t start;
assert(ps && ps->_size>0);
start=0;
while(start<ps->_size-1)
{
ps->_array[start]=ps->_array[start+1];//也是挪动数据
++start;
}
--ps->_size;
}
void SeqListInsert(SeqList *ps,size_t pos,DataType x)//在指定位置插入数据
{
size_t end;
assert(ps);
SeqListCheckCapacity(ps);
end=ps->_size;
while(pos-1<end)//实际要插在原来位置的前一个,另外需要注意的时数组的下标时从0开始的
{
ps->_array[end]=ps->_array[end-1];
--end;
}
ps->_array[pos-1]=x;
ps->_size++;
}
void SeqListErase(SeqList *ps,size_t pos)//删除指定位置
{
size_t start;
assert(ps && ps->_size>0);
start=pos-1;
while(start<ps->_size-1)
{
ps->_array[start]=ps->_array[start+1];
++start;
}
ps->_size=ps->_size-1;
}
size_t SeqListSize(SeqList *ps)//求大小
{
assert(ps);
return ps->_size;
}
size_t SeqListFind(SeqList *ps,DataType x)//查找数据
{
size_t i;
assert(ps && x);
for(i=0; i<SeqListSize(ps); i++)
{
if(ps->_array[i]==x)
{
printf("找到了!位置是%d\n",i+1);
}
else
{
printf("没有找到\n");
break;
}
}
}
DataType SeqListAt(SeqList *ps,size_t pos)//访问pos位置的值
{
assert(ps );
return ps->_array[pos];
}
主函数:
#include "SeqList.h"
void TestSeqList1()
{
size_t i;
SeqList s1;
SeqListInit(&s1);
SeqListPushBack(&s1,1);//尾插
SeqListPushBack(&s1,2);//尾插
SeqListPushBack(&s1,3);//尾插
SeqListPushBack(&s1,4);//尾插
SeqListPushFront(&s1,0);//头插
SeqListPopBack(&s1);
SeqListPushBack(&s1,4);//尾插
SeqListPopFront(&s1);//头删
SeqListInsert(&s1,1,6);//插入
SeqListErase(&s1,1);//删除指定位置
SeqListInsert(&s1,1,6);
for(i=0; i< SeqListSize(&s1); ++i)
{
printf("%d ",SeqListAt(&s1,i));
}
printf("\n");
//SeqListDestory(&s1);
// system("pause");
}
int main()
{
TestSeqList1();
system("pause");
return 0;
}
部分运行截图如下:
尾插四个数据
头插一个数据
尾删一个数据
体现尾插
头删
在指定位置插入数据
删除指定位置的数据