一、顺序表的基本概念
1.顺序存储就是将数据存储到一片连续的内存中,在C语言环境下,可以是具名的栈数组,或者是匿名的堆数组。数组就是一种常见的顺序表。
2.存储方式不仅仅只是提供数据的存储空间,而是必须要能体现数据之间的逻辑关系。当采用顺序存储的方式来存放数据时,唯一能用来表达数据间本身的逻辑关系的就是存储位置。比如队列中的两个人,小明和小花,如果小明在逻辑上排在相邻的小花的前面,那么在存储位置上也必须把小明存放在相邻的小花的前面。
二、顺序表的基本操作
一般而言,为了方便操作顺序表,需要一个专门管理顺序表的”管理结构体“,管理结构体中一般会包含三点:
顺序表总容量
顺序表当前最末元素下标位置
顺序表指针
三、顺序表各种功能的实现
1.初始化
sequenceList *init(int cap)
{
//开辟一个新的空间
sequenceList *s = malloc(sizeof(sequenceList));
if(s != NULL)
{
//赋初始值
s->capacity = cap;
s->last = -1;
//开辟一个新的空间
s->data = malloc(cap * sizeof(int));
//判断是否为空
if(s->data == NULL)
{
//释放该空间
free(s);
//返回空
return NULL;
}
}
return s;
}
2.添加
//bool布尔类型 返回值:true(1) false(0)
//给顺序表添加数据(实现头插)
bool insert(sequenceList *s, int data)
{
int i;
//防止穿进来的是空指针或容量超出
if(s == NULL || (s->last >= s->capacity-1))
return false;
//遍历,把数据往后退
for(i= s->last; i>=0; i--)
{
s->data[i+1] = s->data[i];
}
//把数据头赋值为新添加的数据
s->data[0] = data;
s->last++; //顺序表数据下标加1
return true;
}
3.打印
void display(sequenceList *s)
{
int i;
if(s == NULL)
return;
for(i=0; i <= s->last; i++)
{
printf("%d\t", s->data[i]);
}
printf("\n");
}
4.删除
//删除顺序表数据
bool delete(sequenceList *s, int data)
{
//定义局部变量
int i,j,k=0;
//防止传入空指针
if(s == NULL)
return false;
//遍历
for(i=0 ; i < s->capacity; i++)
{
//判断是不是用户要删除的数据
if (data==s->data[i])
{
k++;
//从那个要删除的数据位置开始全部往前一个位置
for ( j = i; j < s->capacity; j++)
{
s->data[i] = s->data[i+1];
}
}
}
//删除多少个数据,就把后面倒数多少个位置赋空
for ( i = 0; i < k; i++)
{
s->data[s->capacity-1-i] = '\0';
//把最大小标也改了
s->last--;
}
return true;
}
5.查询
//查询顺序表
bool inquire(sequenceList *s, int data)
{
//定义局部变量
int i,e=0;
//防止传入空指针
if(s == NULL)
return false;
//遍历
for(i=0 ; i < s->capacity; i++)
{
//判断是否为用户要查询的数据
if (data==s->data[i])
{
e++;
printf("你查询的数据%d为第%d个数据\n",data,i+1);
}
}
if(e==0)
{
printf("没有找到对应数据,请重新查询其他数据!\n");
}
return true;
}
6.移动
//移动函数(前插)
void move_front(sequenceList *s, int data, int data1)
{
int i,j,k,mept,sum=0;
//遍历
for(i=0 ; i < s->capacity; i++)
{
//判断是否为用户要移动的数据
if (data==s->data[i])
{
sum=1;
break;
}
}
if(sum==0)
{
printf("顺序表中查不到该数据");
return;
}
for(j=0 ; j < s->capacity; j++)
{
//判断是否为用户要移动的数据
if (data1==s->data[j])
{
sum=1;
//进行数据交换
mept=s->data[i];
for ( k = i; k > j; k--)
{
s->data[k]=s->data[k-1];
}
//把需要移动的值添加到指定位置
s->data[j]=mept;
return;
}
}
if(sum==0)
{
printf("顺序表中查无此数据");
return;
}
}
//移动函数(后插)
void move_behind(sequenceList *s, int data, int data1)
{
int i,j,k,mept,sum=0;
//遍历
for(i=0 ; i < s->capacity; i++)
{
//判断是否为用户要移动的数据
if (data==s->data[i])
{
sum=1;
break;
}
}
if(sum==0)
{
printf("顺序表中查不到该数据");
return;
}
for(j=0 ; j < s->capacity; j++)
{
//判断是否为用户要移动的数据
if (data1==s->data[j])
{
sum=1;
//进行数据交换
mept=s->data[i];
for ( k = i; k > j+1; k--)
{
s->data[k]=s->data[k-1];
}
//把需要移动的值添加到指定位置
s->data[j+1]=mept;
return;
}
}
if(sum==0)
{
printf("顺序表中查无此数据");
return;
}
}
7.摧毁
//销毁顺序表
void destroy(sequenceList *s)
{
//防止传入空指针
if(s == NULL)
{
printf("顺序表不存在,不需要摧毁\n");
return;
}
//全部初始化
s->capacity=0;
s->last=-1;
s->data=NULL;
//打印
printf("摧毁顺序表成功\n");
}
下面是完整代码
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
//结构体
typedef struct node
{
int capacity; // 顺序表的数据总个数
int last; // 顺序表最末元素下标
int *data; // 存储数据
}sequenceList;
//声明
void display(sequenceList *s);
sequenceList * init(int cap);
bool insert(sequenceList *s, int data);
bool delete(sequenceList *s, int data);
void destroy(sequenceList *s);
bool inquire(sequenceList *s, int data);
void move_front(sequenceList *s, int data, int data1);
void move_behind(sequenceList *s, int data, int data1);
int main(void)
{
//定义变量
char ch;
int data,i,input,data1;
sequenceList *c;
printf("-------------------------------------------------------------\n");
printf("功能:a:插入数据,b:删除数据,c:查询数据位置,d显示数据\n");
printf(" e:移动数据去目标前,f:移动数据去目标后,g:摧毁\n");
printf("-------------------------------------------------------------\n");
printf("请设置最多能添加的数据个数:");
scanf("%d",&input);
getchar();
//调用函数,生成顺序表
c = init(input);
for(i=0;i<100;i++)
{
printf("请输入功能(a-e):");
ch = getchar();
switch (ch)
{
case 'a':
printf("请输入要插入的数据:");
scanf("%d", &data);
insert(c, data);
break;
case 'b':
printf("请输入要删除的数据:");
scanf("%d", &data);
delete(c, data);
break;
case 'c':
printf("请输入要查询的数据:");
scanf("%d", &data);
inquire(c, data);
break;
case 'd':
display(c);
break;
case 'e':
printf("请输入要移动的那个数据:");
scanf("%d", &data);
printf("要移动到哪个收据的前面:");
scanf("%d", &data1);
move_front(c,data,data1);
break;
case 'f':
printf("请输入要移动的那个数据:");
scanf("%d", &data);
printf("要移动到哪个收据的后面:");
scanf("%d", &data1);
move_behind(c,data,data1);
break;
case 'g':
destroy(c);
break;
default:
printf("输入格式错误,请重新输入!\n");
break;
}
while (getchar() != '\n');
}
//100次循环后自动销毁顺序表
destroy(c);
}
//打印顺序表
void display(sequenceList *s)
{
int i;
if(s == NULL)
return;
for(i=0; i <= s->last; i++)
{
printf("%d\t", s->data[i]);
}
printf("\n");
}
//初始化顺序表
sequenceList *init(int cap)
{
//开辟一个新的空间
sequenceList *s = malloc(sizeof(sequenceList));
if(s != NULL)
{
//赋初始值
s->capacity = cap;
s->last = -1;
//开辟一个新的空间
s->data = malloc(cap * sizeof(int));
//判断是否为空
if(s->data == NULL)
{
//释放该空间
free(s);
//返回空
return NULL;
}
}
return s;
}
//bool布尔类型 返回值:true(1) false(0)
//给顺序表添加数据(实现头插)
bool insert(sequenceList *s, int data)
{
int i;
//防止穿进来的是空指针或容量超出
if(s == NULL || (s->last >= s->capacity-1))
return false;
//遍历,把数据往后退
for(i= s->last; i>=0; i--)
{
s->data[i+1] = s->data[i];
}
//把数据头赋值为新添加的数据
s->data[0] = data;
s->last++; //顺序表数据下标加1
return true;
}
//删除顺序表数据
bool delete(sequenceList *s, int data)
{
//定义局部变量
int i,j,k=0;
//防止传入空指针
if(s == NULL)
return false;
//遍历
for(i=0 ; i < s->capacity; i++)
{
//判断是不是用户要删除的数据
if (data==s->data[i])
{
k++;
//从那个要删除的数据位置开始全部往前一个位置
for ( j = i; j < s->capacity; j++)
{
s->data[i] = s->data[i+1];
}
}
}
//删除多少个数据,就把后面倒数多少个位置赋空
for ( i = 0; i < k; i++)
{
s->data[s->capacity-1-i] = '\0';
//把最大小标也改了
s->last--;
}
return true;
}
//查询顺序表
bool inquire(sequenceList *s, int data)
{
//定义局部变量
int i,e=0;
//防止传入空指针
if(s == NULL)
return false;
//遍历
for(i=0 ; i < s->capacity; i++)
{
//判断是否为用户要查询的数据
if (data==s->data[i])
{
e++;
printf("你查询的数据%d为第%d个数据\n",data,i+1);
}
}
if(e==0)
{
printf("没有找到对应数据,请重新查询其他数据!\n");
}
return true;
}
//销毁顺序表
void destroy(sequenceList *s)
{
//防止传入空指针
if(s == NULL)
{
printf("顺序表不存在,不需要摧毁\n");
return;
}
//全部初始化
s->capacity=0;
s->last=-1;
s->data=NULL;
//打印
printf("摧毁顺序表成功\n");
}
//移动函数(前插)
void move_front(sequenceList *s, int data, int data1)
{
int i,j,k,mept,sum=0;
//遍历
for(i=0 ; i < s->capacity; i++)
{
//判断是否为用户要移动的数据
if (data==s->data[i])
{
sum=1;
break;
}
}
if(sum==0)
{
printf("顺序表中查不到该数据");
return;
}
for(j=0 ; j < s->capacity; j++)
{
//判断是否为用户要移动的数据
if (data1==s->data[j])
{
sum=1;
//进行数据交换
mept=s->data[i];
for ( k = i; k > j; k--)
{
s->data[k]=s->data[k-1];
}
//把需要移动的值添加到指定位置
s->data[j]=mept;
return;
}
}
if(sum==0)
{
printf("顺序表中查无此数据");
return;
}
}
//移动函数(后插)
void move_behind(sequenceList *s, int data, int data1)
{
int i,j,k,mept,sum=0;
//遍历
for(i=0 ; i < s->capacity; i++)
{
//判断是否为用户要移动的数据
if (data==s->data[i])
{
sum=1;
break;
}
}
if(sum==0)
{
printf("顺序表中查不到该数据");
return;
}
for(j=0 ; j < s->capacity; j++)
{
//判断是否为用户要移动的数据
if (data1==s->data[j])
{
sum=1;
//进行数据交换
mept=s->data[i];
for ( k = i; k > j+1; k--)
{
s->data[k]=s->data[k-1];
}
//把需要移动的值添加到指定位置
s->data[j+1]=mept;
return;
}
}
if(sum==0)
{
printf("顺序表中查无此数据");
return;
}
}
运行效果图如下: