顺序表练习

本文介绍了顺序表的基本概念,区分了静态和动态顺序表,并重点讲述了动态顺序表的实现,包括创建、插入、删除、遍历和排序等功能。动态顺序表通过指针变量在堆上分配空间,能灵活改变表的长度,避免了静态顺序表的空间不足或浪费问题。
摘要由CSDN通过智能技术生成

顺序表简单定义

        顺序表是线性存储的一种,其存储的内容是相同类型,且在内存中存储是连续的。在计算机中,顺序表的存储形式是通过数组来展现的,通过连续的地址来存储其内容。

顺序表的分类

        静态顺序表:表长度确定,无法被改变,类似于

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值