顺序表简单定义
顺序表是线性存储的一种,其存储的内容是相同类型,且在内存中存储是连续的。在计算机中,顺序表的存储形式是通过数组来展现的,通过连续的地址来存储其内容。
顺序表的分类
静态顺序表:表长度确定,无法被改变,类似于
#define N 200
int a[N]; //长度固定无法改变
动态顺序表:表长度使用指针变量,通过malloc在堆上分配空间,表的长度可以被改变
struct SeqList
{
int *a; //指向顺序表的指针
int count; //顺序表中的有效元素个数
int len; //顺序表的长度
}
因为静态顺序表的大小固定,可能会导致空间不够或者空间浪费的情况,且功能与动态顺序表几乎没有太大差异,所以普遍选择采用动态顺序表!
顺序表简单实现的功能
功能:创建、插入、任意位置插入、任意位置删除、遍历、排序
功能实现:
头文件:
#ifndef _SEQ_LIST_H_
#define _SEQ_LIST_H_
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct data
//创建数据结构体
{
int data;
char datac;
}DATA,*QDATA;
typedef struct seq_list
{
//创建存储结构体
QDATA q;
//创建数据结构体指针,用于创建动态
//顺序表
int count;
//计数器,用于记录顺序表存储的有效数据个数
int len;
//顺序表长度
}SEQ,*QSEQ;
bool empty(QSEQ);
bool ifnull(QSEQ);
bool full(QSEQ);
void seq_list_create2(QSEQ,int);
void seq_list_create(QSEQ *);
void seq_list_insert(QSEQ,DATA);
void seq_list_insert2(QSEQ,QDATA);
void seq_list_traversal(QSEQ);
void seq_list_insert_pop(QSEQ,int,DATA);
void seq_list_delete(QSEQ,int);
void seq_list_sort(QSEQ);
#endif
具体函数功能实现
创建功能
注:*Q->q是不允许的写法(记住),但有不同的写法可以避免这种情况出现,下有解释
void seq_list_create(QSEQ *Q)
//创建顺序表
{
if(NULL==Q)
//判断传递的值是否为空
{
printf("入参为NULL,请重新传参\n");
return;
}
//为指针变量赋值,创建顺序表
*Q=(QSEQ)malloc(sizeof(SEQ));
if(ifnull(*Q))
{
printf("空间分配失败!\n");
return;
}
}
void seq_list_create2(QSEQ Q,int lenth)
{
//创建顺序表并为表内的变量赋值
//(*Q被认定为指针,无法使用*Q->的写法)
//所以只能拆开两个函数来实现创建表。
//另外,也有其他的方法可以实现一个函数创建表
//比如传递指针变量,然后通过返回值返回
//但此次未采用上述写法,所以要多思考,
//在彻底掌握前一定要多想!要多想!要多想!
Q->len=lenth;
Q->count=0;
Q->q=(QDATA)malloc(sizeof(DATA)*lenth);
//创建顺序表,在堆上分配表的长度(所占用空间)
if(NULL==Q->q)
{
printf("空间分配失败!\n");
return;
}
return;
}
插入功能
void seq_list_insert(QSEQ Q,DATA D)
{
//在顺序表内插入数据,数据类型为DATA结构体类型
if(ifnull(Q))
//判断传参是否为NULL(指针指向NULL)
{
printf("入参为NULL!\n");
return;
}
if(full(Q))
//判断表是否已满,若表满无法插入数据
{
printf("表已满,无法插入\n");
return;
}
Q->q[Q->count]=D;
//将数据插入第count位
Q->count++;
//count(有效数据个数)增加1位
return;
}
循环插入功能
void seq_list_insert2(QSEQ Q,QDATA D)
//循环插入元素,直到表满
{
if(ifnull(Q))
{
printf("入参为NULL!\n");
return;
}
if(full(Q))
{
printf("表已满,无法插入\n");
return;
}
int i=0;
while(Q->count!=Q->len)
//判断条件为表不满便执行,表满结束
{
Q->q[Q->count]=D[i];
i++;
Q->count++;
}
return;
}
指定位置插入功能
void seq_list_insert_pop(QSEQ Q,int pop,DATA D)
//在指定的位置插入元素
//形参pop可以是数据位也可以是下标位
//不过对pop的判断条件需要改变
//本函数采用的是数据位
{
if(ifnull(Q))
{
printf("入参为NULL!\n");
return;
}
if(full(Q))
{
printf("表已满!\n");
return;
}
if(pop<1||pop>Q->count+1)
//数据位不能小于1,也不能大于已有元素的下一位
//因为可以插入在有效元素的后一位,但是不能插入
//后一位的后一位(顺序表是连续的插入的元素位置也要满足连续性)
{
printf("所输入的参数有误\n");
}
int i=0;
for(i=Q->count;i>pop-1;i--)
//写功能时也需要考虑到是否会溢出
//配合画图效果更好
{
Q->q[i]=Q->q[i-1];
}
Q->q[i]=D;
Q->count++;
return;
}
遍历功能
void seq_list_traversal(QSEQ Q)
//遍历表
{
if(empty(Q))
//判断是否为空表,若为空表不执行遍历
{
printf("表为空!\n");
return;
}
int i=0;
while(i<Q->count)
//遍历表内数据,循环输出
{
printf("%dand%c\n",Q->q[i].data,Q->q[i].datac);
i++;
}
return;
}
指定位置删除功能
void seq_list_delete(QSEQ Q,int pop)
//删除指定位置数据
//本次pop采用的是下标位
//其余思想和指定位置插入数据函数相似
{
if(ifnull(Q))
{
printf("NULL\n");
return;
}
if(empty(Q))
{
printf("表为空!\n");
return;
}
if(pop<0||pop>Q->count-1)
//pop是下标位,下标不能小于0
//也不能大于已有效元素数量(count)-1
{
printf("输入参数不符合要求\n");
return;
}
int i=0;
DATA j;
j=Q->q[pop];
//将所要删除的数据赋值给j,并输出提示
for(i=pop;i<Q->count-1;i++)
//也要考虑数据交换的溢出问题
//要多思考!
{
Q->q[i]=Q->q[i+1];
}
Q->count--;
printf("所删除的值为%dand%c\n",j.data,j.datac);
return;
}
排序功能
void seq_list_sort(QSEQ Q)
//顺序表数据排序
{
if(ifnull(Q))
{
printf("NULL\n");
return;
}
if(empty(Q))
{
printf("空\n");
return;
}
int i=0;
int j=0;
DATA t;
//交换变量
//三杯水原则
for(i=0;i<Q->count-1;i++)
{
for(j=i+1;j<Q->count;j++)
{
if(Q->q[i].data<Q->q[j].data)
//按照从大到小的顺序排序
{
t=Q->q[i];
Q->q[i]=Q->q[j];
Q->q[j]=t;
}
}
}
seq_list_traversal(Q);
return;
}
完整函数功能实现
#include"seq-list.h"
bool ifnull(QSEQ a)
//判断传递的实参指针是否为空
{
if(NULL==a)
{
return true;
}
else
{
return false;
}
}
bool full(QSEQ A)
//判断表是否已满
{
if(A->count==A->len)
{
return true;
}
else
{
return false;
}
}
bool empty(QSEQ A)
//判断表是否为空
{
if(A->count==0)
{
return true;
}
else
{
return false;
}
}
void seq_list_create(QSEQ *Q)
//创建顺序表
{
if(NULL==Q)
//判断传递的值是否为空
{
printf("入参为NULL,请重新传参\n");
return;
}
//为指针变量赋值,创建顺序表
*Q=(QSEQ)malloc(sizeof(SEQ));
if(ifnull(*Q))
{
printf("空间分配失败!\n");
return;
}
}
void seq_list_create2(QSEQ Q,int lenth)
{
//创建顺序表并未表内的变量赋值
//(*Q被认定为指针,无法使用*Q->的写法)
//所以只能拆开两个函数来实现创建表。
//另外,也有其他的方法可以实现一个函数创建表
//比如传递指针变量,然后通过返回值返回
//但此次未采用上述写法,所以要多思考,
//在彻底掌握前一定要多想!要多想!要多想!
Q->len=lenth;
Q->count=0;
Q->q=(QDATA)malloc(sizeof(DATA)*lenth);
//创建顺序表,在堆上分配表的长度(所占用空间)
if(NULL==Q->q)
{
printf("空间分配失败!\n");
return;
}
return;
}
void seq_list_insert(QSEQ Q,DATA D)
{
//在顺序表内插入数据,数据类型为DATA结构体类型
if(ifnull(Q))
//判断传参是否为NULL(指针指向NULL)
{
printf("入参为NULL!\n");
return;
}
if(full(Q))
//判断表是否已满,若表满无法插入数据
{
printf("表已满,无法插入\n");
return;
}
Q->q[Q->count]=D;
//将数据插入第count位
Q->count++;
//count(有效数据个数)增加1位
return;
}
void seq_list_insert2(QSEQ Q,QDATA D)
//循环插入元素,直到表满
{
if(ifnull(Q))
{
printf("入参为NULL!\n");
return;
}
if(full(Q))
{
printf("表已满,无法插入\n");
return;
}
int i=0;
while(Q->count!=Q->len)
//判断条件为表不满便执行,表满结束
{
Q->q[Q->count]=D[i];
i++;
Q->count++;
}
return;
}
void seq_list_traversal(QSEQ Q)
//遍历表
{
if(empty(Q))
//判断是否为空表,若为空表不执行遍历
{
printf("表为空!\n");
return;
}
int i=0;
while(i<Q->count)
//遍历表内数据,循环输出
{
printf("%dand%c\n",Q->q[i].data,Q->q[i].datac);
i++;
}
return;
}
void seq_list_insert_pop(QSEQ Q,int pop,DATA D)
//在指定的位置插入元素
//形参pop可以是数据位也可以是下标位
//不过对pop的判断条件需要改变
//本函数采用的是数据位
{
if(ifnull(Q))
{
printf("入参为NULL!\n");
return;
}
if(full(Q))
{
printf("表已满!\n");
return;
}
if(pop<1||pop>Q->count+1)
//数据位不能小于1,也不能大于已有元素的下一位
//因为可以插入在有效元素的后一位,但是不能插入
//后一位的后一位(顺序表是连续的插入的元素位置也要满足连续性)
{
printf("所输入的参数有误\n");
}
int i=0;
for(i=Q->count;i>pop-1;i--)
//写功能时也需要考虑到是否会溢出
//配合画图效果更好
{
Q->q[i]=Q->q[i-1];
}
Q->q[i]=D;
Q->count++;
return;
}
void seq_list_delete(QSEQ Q,int pop)
//删除指定位置数据
//本次pop采用的是下标位
//其余思想和指定位置插入数据函数相似
{
if(ifnull(Q))
{
printf("NULL\n");
return;
}
if(empty(Q))
{
printf("表为空!\n");
return;
}
if(pop<0||pop>Q->count-1)
//pop是下标位,下标不能小于0
//也不能大于已有效元素数量(count)-1
{
printf("输入参数不符合要求\n");
return;
}
int i=0;
DATA j;
j=Q->q[pop];
//将所要删除的数据赋值给j,并输出提示
for(i=pop;i<Q->count-1;i++)
//也要考虑数据交换的溢出问题
//要多思考!
{
Q->q[i]=Q->q[i+1];
}
Q->count--;
printf("所删除的值为%dand%c\n",j.data,j.datac);
return;
}
void seq_list_sort(QSEQ Q)
//顺序表数据排序
{
if(ifnull(Q))
{
printf("NULL\n");
return;
}
if(empty(Q))
{
printf("空\n");
return;
}
int i=0;
int j=0;
DATA t;
//交换变量
//三杯水原则
for(i=0;i<Q->count-1;i++)
{
for(j=i+1;j<Q->count;j++)
{
if(Q->q[i].data<Q->q[j].data)
//按照从大到小的顺序排序
{
t=Q->q[i];
Q->q[i]=Q->q[j];
Q->q[j]=t;
}
}
}
seq_list_traversal(Q);
return;
}
主函数:
#include"seq-list.h"
int main(int argc, const char *argv[])
{
QSEQ Q=NULL;
//创建结构体指针
seq_list_create(&Q);
seq_list_create2(Q,6);
DATA a={1,'A'};
DATA b[6]=
{{2,'B'},{3,'C'},{4,'D'},{5,'E'},{6,'F'},{7,'G'}};
seq_list_insert(Q,a);
seq_list_insert2(Q,b);
seq_list_traversal(Q);
seq_list_delete(Q,4);
seq_list_insert_pop(Q,3,a);
seq_list_traversal(Q);
printf("\n");
seq_list_sort(Q);
free(Q->q);
//销毁顺序表
free(Q);
Q=NULL;
return 0;
}