参考顺序表
一、顺序存储
线性表是顺序存储结构指用一段地址连续的存储单元依次存储线性表的数据元素。
也就是说,逻辑上具有线性关系的数据按照前后顺序关系依次全部存储在一块连续的内存空间中;
使用顺序存储结构的数据,其第一个元素对应地址为该存储空间的首地址,通过首地址,可以依次访问到其他元素。
使用线性表的顺序存储结构生成的表称为顺序表。
顺序表实现
顺序表中存放数据特点和数组数据类型相似,故使用数组来实现顺序表功能,这里使用动态内存分配;
注:使用数组实现顺序表的存储结构时,需要预先申请足够大的内存空间,否则存储空间不足,会导致数据溢出,程序报错甚至崩溃。
定义顺序表的结构
#include<stdio.h>
#include<malloc.h>
#define Size 20
typedef struct Table{
int *head;//声明一个名为head长度不确定的数组,即“动态数组”
int length;//记录当前顺序表的长度
int size;//记录当前顺序表的存储容量
}table;
创建顺序表
先顺序表初始化,在预先申请内存空时,给顺序表空间size和长度length赋初值
//顺序表创建
table initTable() //table ..?int initTable->返回值为整型,这里返回值为table
{
table t;
t.head = (int*)malloc(Size*sizeof(int));
if(!t.head)
{
printf("fail");
//perro("fail");//undifined reference to perro
//return -1;
//exit(0);//incompatible implict declaration of built-in function exit
}
t.length = 0; //空表长度初始化为0
t.size=Size; //空表的初始化存储空间为Size
printf("init sucess %d:", t.size);
return t;
}
/*
init sucess 20:
原顺序表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
show success:*/
查找元素
数组查找元素时,可采用多种算法,例如二分法、插值查找方法、斐波那契查找算法...
这里采用顺序查找法
//顺序表查找元素,查找函数。elem:要查找的数据元素的值
int selectTable(table t, int elem){
int i;
for(i=0;i<t.length;i++){
if(t.head[i]==elem)
{
return i+1;
}
}
return -1;//如果查找失败,返回-1
}
/*
查找元素4的位置:
4*/
更改顺序表中元素
根据位置查找到该元素,然后给该位置上赋一个新值
//顺序表中更改元素
table changeTable(table t, int elem,int newelem){
int i;
for(i=0;i<t.length;i++){ //for (int i=0;;)//only allowed in C99 or C11 mode
int n = selectTable(t, elem);
t.head[n-1] = newelem;//返回值n为元素在顺序表中位置,n-1为该元素在数组中的下标
return t;
}
}
/*
将元素3改为6:
1 2 6 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/
插入元素
插入数据元素涉及三种方式:1、在表头插入;2、在表中间插入;3、在表尾插入;
无论哪个位置,只要先找打要插入位置,然后将数据元素整体向后移动一个位置,在腾出空间位置上 插入元素。
//顺序表插入元素:表头、表中、表尾
//插入函数,elem为插入元素,add为插入到顺序表位置
table insertTable(table t, int elem, int add){
//判断 插入本身是否有问题,插入元素位置是否比整张表长度+1还大(相等为表尾)
//插入的位置本身不存在,程序提示自动退出
if(add>t.length+1 || add<1){
printf("插入位置出错:\n");
return t;
}
//做插入时,先看顺序表是否存在多余空间给插入元素,若没有需申请
if(t.length == t.size){
t.head = (int *)realloc(t.head,(t.size+1)*sizeof(int));
if(!t.head){
printf("内存分配失败:\n");
return t;
}
t.size+=1;//??
}
int i;
//插入操作,需将从插入位置开始的后需元素,逐个后移
for(i=t.length-1;i>=add-1;i--){
t.head[i+1]=t.head[i];
}
//后移完成 ,直接将所需插入位置开始元素,添加到顺序表的相应位置
t.head[add-1]=elem;
t.length++;
return t;
}
/*
在第4位置插入元素9:
1 2 6 9 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/
删除元素
删除该元素时,让该元素所在位置后的所有数据元素整体向前移动一个位置,被删除元素的值被覆盖。
//顺序表删除元素
table delTable(table t, int del){
if(del>t.length && del<1 ){
printf("del set erro:\n");
//exit(0);
}
//del operation
int i;
for(i=del;i<t.length;i++)
{
t.head[i-1]=t.head[i];
}
t.length--;
return t;
}
/*
删除元素:
2 6 9 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/
完整代码演示
#include<stdio.h>
#include<malloc.h>
#define Size 20
typedef struct Table{
int *head;//声明一个名为head长度不确定的数组,即“动态数组”
int length;//记录当前顺序表的长度
int size;//记录当前顺序表的存储容量
}table;
//顺序表创建
table initTable() //table ..?int initTable->返回值为整型,这里返回值为table
{
table t;
t.head = (int*)malloc(Size*sizeof(int));
if(!t.head)
{
printf("fail");
//perro("fail");//undifined reference to perro
//return -1;
//exit(0);//incompatible implict declaration of built-in function exit
}
t.length = 0; //空表长度初始化为0
t.size=Size; //空表的初始化存储空间为Size
printf("init sucess %d:\n", t.size);
return t;
}
//顺序表查找元素,查找函数。elem:要查找的数据元素的值
int selectTable(table t, int elem){
int i;
for(i=0;i<t.length;i++){
if(t.head[i]==elem)
{
return i+1;
}
}
return -1;//如果查找失败,返回-1
}
//顺序表中更改元素
table changeTable(table t, int elem,int newelem){
int i;
for(i=0;i<t.length;i++){ //for (int i=0;;)//only allowed in C99 or C11 mode
int n = selectTable(t, elem);
t.head[n-1] = newelem;//返回值n为元素在顺序表中位置,n-1为该元素在数组中的下标
return t;
}
}
//顺序表插入元素:表头、表中、表尾
//插入函数,elem为插入元素,add为插入到顺序表位置
table insertTable(table t, int elem, int add){
//判断 插入本身是否有问题,插入元素位置是否比整张表长度+1还大(相等为表尾)
//插入的位置本身不存在,程序提示自动退出
if(add>t.length+1 || add<1){
printf("插入位置出错:\n");
return t;
}
//做插入时,先看顺序表是否存在多余空间给插入元素,若没有需申请
if(t.length == t.size){
t.head = (int *)realloc(t.head,(t.size+1)*sizeof(int));
if(!t.head){
printf("内存分配失败:\n");
return t;
}
t.size+=1;//??
}
int i;
//插入操作,需将从插入位置开始的后需元素,逐个后移
for(i=t.length-1;i>=add-1;i--){
t.head[i+1]=t.head[i];
}
//后移完成 ,直接将所需插入位置开始元素,添加到顺序表的相应位置
t.head[add-1]=elem;
t.length++;
return t;
}
//顺序表删除元素
table delTable(table t, int del){
if(del>t.length && del<1 ){
printf("del set erro:\n");
//exit(0);
}
//del operation
int i;
for(i=del;i<t.length;i++)
{
t.head[i-1]=t.head[i];
}
t.length--;
return t;
}
void showTable(table t){
int i;
for(i=0;i<t.length;i++){
printf("%d ", t.head[i]);
}
//printf("\n show success:\n");
}
int main(){
table t1 = initTable();
int i;
for(i=1;i<Size;i++){
t1.head[i-1]=i;
t1.length++;
//printf("%d ", t1.head[i]);
}
printf("原顺序表: \n");
showTable(t1);
printf("查找元素4的位置: \n");
int add = selectTable(t1, 4);
printf("%d\n",add);
printf("将元素3改为6:\n");
t1 = changeTable(t1,3,6);
showTable(t1);
printf("\n在第4位置插入元素9:\n");
t1 = insertTable(t1,9,4);
showTable(t1);
printf("\n 删除元素: \n");
t1 = delTable(t1,1);
showTable(t1);
return 0;
}
小结:
线性表的顺序存储主要通过动态内存分配存储空间,初始化表的长度及最大容量;通过结构体指针给表中元素赋值,区别链式存储,这里没有使用指针域来指向下一个结点,更多的类似数组访问结点,只是使用动态存储分配,在程序运行后才给定线性表空间。