今天来分享一下最近所学,顺便巩固一下自己的知识。
目录
创建一个空的顺序表
个人认为顺序表的实质就是动态数组的实现,所以要动态向内存申请空间
要先定义一个结构体用来封装顺序表的属性,访问顺序表就是通过这个顺序表的顺序表属性里的data来访问的
struct array
{
short length;//顺序表中数据的个数
short size;//顺序表所占内存的大小
short* data;//指向顺序表首元素的指针
};
这个顺序表中所存放的数据为short类型的数据,下面是顺序表的创建
array* creat_array()//创建一个顺序表属性
{
array* temp=(array*)malloc(sizeof(array));
assert(temp);//断言函数
temp->data=(short*)malloc(sizeof(short))//申请一块内存空间,表示将来顺序表的首地址
assert(temp->data);
temp->length=0;//length=0表示现在顺序表里面还没有数据
temp->size=1;//顺序表中short空间的个数
return temp;//返回
}
数据的插入
顺序表和静态数组的最大不同之处就在于它可以扩容,
数据插入函数,要判断是插入在什么位置(是否合法),要插入的数据 ,
这里只写每次只插入一个数据的函数,并且插入位置只能在1~length+1之间,
顺序表中间不能有空的位置,如果有空的位置,在遍历顺序表时会报错,
void insert_data(array* temp,short data,short n)//分别代表顺序表的属性,要插入的数据,要插入的位置
{
if(n<1||n>temp->length)//判断插入位置是否合法
{
printf("插入位置不合法\n");
return;
}
if(temp->length>=temp->size)//判断顺序表是否满了,如果满了应该扩容
{
temp->data=(short*)realloc(sizeof(short)*(temp->length+1));
temp->size+=1;//顺序表属性改变,内存空间增大加1
}
//length和n都代表的是位置,和下标差1
for(short i=temp->length-1;i>=n-1;--i)//将下标大于等于n-1数据向后移动,(包括n-1)
{
temp->data[i+1]=temp-data[i];
}
temp-data[n-1]=data;//将要插入的数据赋值给第n个位置,也就是下标为n-1的数组元素
temp->length++;//顺序表属性中的长度+1
}
元素的查找
顺序表中查找某个数据思想就是遍历数组,如果找到了就输出这个数据所在的位置,没有就提示顺序表中没有这个数据。
当然查找的前提是顺序表中还有元素
查找函数实现功能,查找某个数据在顺序表中的位置,并且输出这个数据在顺序表中出现了多少次
void search_data(array* temp,short data)
{
if(temp->length<=0)//判断顺序表是否为空
{
printf("顺序表为空\n");
return;
}
short num=0;//记录data在顺序表中出现的次数
for(short i=0;i<temp->length;++i)
{
if(temp->data[i]==data)//
{
printf("%d在第%d个位置上。\n",data,i);
num++;
}
}
if(num)//如果num!=0的
{
printf("%d在顺序表中出现了%d次\n",data,num);
}
else
{
printf("%d不在顺序表中\n",data);
}
}
数据的删除
顺序表中数据的删除并不想链表那样可以之间将节点释放掉,而是通过改变temp->length的值来设置访问权限,
也就是说,顺序表中数据的删除就是将数据删除,但是内存空间还在。
当然删除的前提是顺序表中还有数据
删除函数
这里的删除函数,有两种:
1、删除指定位置 (只删除一个,而且只要位置合法必定会删除数据)
2、删除指定数据(删除若干个或者一个也不删除,无需考虑删除位置,)
这里就拿第一种为例,因为第一种个简单易懂,第二种只是在第一种的基础上稍作改进就可以了,就只是用一个嵌套的for循环
void del_data(array* temp,short n)//n代表删除位置
{
if(temp->length<1)//判断顺序表中是否还有数据
{
printf("顺序表已经空了。\n");
return;
}
if(n<1||n>temp->length)//判断删除位置是否合法
{
printf("删除位置不合法\n");
return;
}
for(short i=n-1;i<temp->length;++i)//将后面数据依次向前移动,将要删除的数据覆盖掉
{
temp->data[i]=temp->data[i+1];
}
temp-length--;//删除之后顺序表的属性改变,length-1
}
修改数据
修改顺序表中某个位置上的数据,前提顺序表还有元素
修改函数,还是和删除类似,有两种函数:
1、修改指定位置
2、修改指定数据
void change_data(array*temp,short n,short new_data)//n 要修改的位置,new_data修改之后的数据,
{
if(temp->length<=0)
{
printf("顺序表为空。\n");
return;
}
if(n<1||n>temp->length)//位置不合法
{
printf("修改位置不合法。\n");
return;
}
temp->data[n-1]=new-data;
}
数据输出
将顺序表中的数据进行输出
void print_array(array*temp)
{
if(temp->length<=0)//空表,返回
return;
for(short i=0;i<temp->length;++i)
{
printf("%d ",temp->data[i]);
}
printf("\n");
}
最后
顺序表基本总结完了,总的来说顺序表还是比较简单的,实现了动态数组的功能,
但是顺序表一般用来存放那些一般删除,插入操作很少的数据,因为顺序表要插入一个数据,如果是插在表尾的话还好说,顺序表中没有数据移动时间复杂度为O(1),但是如果要插在表头的话整个顺序表中的数据都要向后移动时间复杂度为O(n),这样的效率会很低,
所以顺序表一般用来读取数据,和从末尾插入数据。顺序表一般用在像账号注册那种情况下,,顺序表虽然插入删除效率很低,但是读取数据效率却很高,给定位置直接就读取出来了。
链表很好的解决了插入删除效率低的问题,但是读取效率又很低,链表会趁着五一小长假整理出来的,
语言组织能力还是有点欠缺,阅读不舒畅还请见谅。
希望能对读者有点帮助,让我们共同进步
下一篇,是在顺序表的基础上实现冒泡排序,选择排序,插入排序和快速排序,顺便再总结一下桶排序