此篇为重构之前的练习
使用线性连续存储结构来写一个信息管理程序
要求要尽量提高复用性,其次因为使用的这种存储结构的劣势约束,在这里使用动态内存分配来进行一定的弥补
功能:功能包括:初始化,追加数据,从某位置插入数据,删除数据,判断数据是否为空,为数据排序,遍历输出数据,将数据进行倒置
代码展示:
预备工作
一开始首先要初始化数据,我在初始话之前先定义了一个结构体(类)其中包含三个成员,分别是:
struct Arr
{
int* pBase; //存储的是数组第一个元素的首地址
int len; //数组所能容纳的最大元素的个数
int cnt; //当前数组有效元素的个数
//int increment; //自动增长因子
};
定义这个结构体的目的是为了让我更好的对数组进行操作,后面慢慢说。
初始化
void init_arr(struct Arr* parr,int len) //初始化结构体
{
//parr->len=99;
parr->pBase = (int*)malloc(sizeof(int) * len);
if (NULL == parr->pBase)
{
printf("动态内存分配失败");
exit(-1); //终止
}
else
{
parr->cnt = 0;
parr->len = len;
}
return;
}
其实初始化就是要用户给出一个用户需要的数组长度,在内存中动态开辟出空间,这样就初始化完毕了,在这里需要判断内存是否开辟成功,及判断返回的地址是否为空,如果为空那就是没有成功,否则的话我们就把结构体中的长度和有效元素个数初始化就可以了
遍历输出数据
我比较懒,觉得这个功能比较简单所以先写这个了,当然先写后写没什么区别了
void show_arr(struct Arr* parrshow) //输出数组
{
if (is_empty(parrshow))
printf("数组为空\n");
else
{
//printf("%d %d %s", parrshow->cnt, parrshow->len, parrshow->pBase);
for (int i = 0; i < parrshow->cnt; ++i)
{
//printf("%d", *(parrshow[i].pBase));
printf("%d\t", (parrshow->pBase)[i]);
//printf("%d", parrshow->pBase[i]);--ok
}
}
printf("\n");
}
遍历输出数组,这个不要太简单,不做详解,不过就是要注意,我们遍历输出前先要判断数组是否为空,我们虽然已经按用户要求创建好了数组在输出前内部还都是垃圾值,所以先要判断内部是否有有效数组,机判断是否为空
判断数组是否为空
bool is_empty(struct Arr* parrempty)//判断是否为空
{
if (0 == parrempty->cnt)
return true;
else
return false;
}
追加数据
添加数据有两种方式,一种是追加数据,一种是插入数据两种方式不太一样,我们先来个简单的——在数据的最后的有效数据后在添加数据,这时需要考虑的是数组是否已经满,再一个需要考虑的地方是,添加元素有可能会成功或者失败,所以我们需要返回一个布尔值来提醒用户是否添加成功
bool append_arr(struct Arr* parr, int val)//往数组中追加数据
{
//满时返回false
if (is_full(parr))
return false;
else//不满时追加
{
parr->pBase[parr->cnt] = val;
parr->cnt ++;
return true; //表示往里面添加元素成功
}
}
判断数组是否满
这个比较简单,当然涉及到返回布尔值,那就是代表程序可以偷懒了
下面是偷懒(完美)的写法
bool is_full(struct Arr* parr)//判断数组是否满
{
return(parr->cnt == parr->len);
}
还有不偷懒(不完美)的写法:
bool is_full(struct Arr* parr)//判断数组是否满
{
//不够好的代码
if (parr->cnt == parr->len)
return true;
else
return false;
}
我当然是选择上种。
插入数据
结合着追加数据的热度,我们开始思考如何再数组中插入数据
首先就是要判断数据是否已满,慢的话就不能插入了呗。
其次就是要明白数据不能乱插,只能查在有效数据个数+1的位置之前,比如你这个数组中只有两个元素,但是你想插在下标为4的位置,那就不行了
再其次如果你插入的话,要把插入位置及以后的有效数据都往后移动一位
最后用户给的位置可能不合法,这个也要想到
看成果:
bool insert_arr(struct Arr* parr, int pos, int val)
{
if (is_full(parr) || pos<1 || pos>parr->cnt+1) //
return false;
else
{
int i;
for (i = parr->cnt - 1;i>=pos-1;--i)
{
parr->pBase[i+1] = parr->pBase[i];
}
parr->pBase[pos - 1] = val;
parr->cnt++;
return true;
}
}
删除指定位置数据
删除数据跟插入数据需要考虑的问题类似
bool delete_arr(struct Arr* parr, int pos, int* pval)
{
if (is_empty(parr) || pos<1 || pos>parr->cnt)
return false;
else
{
*pval = parr->pBase[pos - 1];
for (int i = pos; i < parr->cnt; ++i)
{
parr->pBase[i - 1] = parr->pBase[i];
}
parr->cnt--;
return true;
}
}
数据倒置
void inversion_arr(struct Arr* parr)
{
int i = 0;
int j = parr->cnt - 1;
int t;
while (i < j)
{
t = parr->pBase[i];
parr->pBase[i] = parr->pBase[j];
parr->pBase[j] = t;
++i;
--j;
}
return;
}
这个在之前介绍过了,很简单不多说
排序
无论是简单选择还是冒泡抑或是简单+冒泡都可以,
void sort_arr(struct Arr* parr)
{
int i, j,t;
for (i = 0; i < parr->cnt-1; ++i)
{
for (j = i+1; j <= parr->cnt-1;++j)
{
if (parr->pBase[i] > parr->pBase[j])
{
t = parr->pBase[i];
parr->pBase[i] = parr->pBase[j];
parr->pBase[j] = t;
}
}
}
}
//void sort_arr(struct Arr* parr)
//{
// int i, j, t;
// for (i = 0; i < parr->cnt - 1; ++i)
// {
// for (j = i; j < parr->cnt - 1-i; ++j)
// {
// if (parr->pBase[i] > parr->pBase[j+1])
// {
// t = parr->pBase[i];
// parr->pBase[i] = parr->pBase[j+1];
// parr->pBase[j+1] = t;
// }
// }
// }
//}
//void sort_arr(struct Arr* parr)
//{
//int i, j, t;
// for (i = 0; i < parr->cnt - 1; ++i)
//{
// for (j = 0; j < parr->cnt - 1 - i; ++j)
// {
// if (parr->pBase[j] > parr->pBase[j + 1])
// {
// t = parr->pBase[j];
// parr->pBase[j] = parr->pBase[j + 1];
// parr->pBase[j + 1] = t;
// }
// }
//}
//}
这个以前的文章中也有,不多说
源码
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<ostream>
#include<stdlib.h> //包含了exit函数
struct Arr
{
int* pBase; //存储的是数组第一个元素的首地址
int len; //数组所能容纳的最大元素的个数
int cnt; //当前数组有效元素的个数
//int increment; //自动增长因子
};
void init_arr(struct Arr * parr,int len);//初始化
bool append_arr(struct Arr * parr,int val);//追加
bool insert_arr(struct Arr* parr, int pos,int val);//插入 pos的值从1开始
bool delete_arr(struct Arr* parr, int pos,int*pval);//删除 考率
bool is_empty(struct Arr* parrempty);//判断是否为空
bool is_full(struct Arr* parr);//判断是否满
void sort_arr(struct Arr* parr);//排序
void show_arr(struct Arr*parrshow);//输出
void inversion_arr(struct Arr* parr);//倒置
int main(void)
{
struct Arr arr;
int len = 6;
int val;
init_arr(&arr,len);
show_arr(&arr);//输出
//printf("%d", arr.len);
append_arr(&arr, 44);
append_arr(&arr, 21);
append_arr(&arr, 111);
append_arr(&arr, 3);
//append_arr(&arr, 5);
if (append_arr(&arr, 66))
printf("追加成功\n");
else
printf("追加失败\n");
//插入
insert_arr(&arr, 1, 99);
if (append_arr(&arr, 7))
printf("追加成功\n");
else
printf("追加失败\n");
insert_arr(&arr, 3, 199);
if (delete_arr(&arr, 1, &val))
{
printf("删除成功,,您删除的元素是%d\n",val);
}
else
printf("删除失败了个球的\n");
if (delete_arr(&arr, 5, &val))
{
printf("删除成功,,您删除的元素是%d\n", val);
}
else
printf("删除失败了个球的\n");
if (delete_arr(&arr, 5, &val))
{
printf("删除成功,,您删除的元素是%d\n", val);
}
else
printf("删除失败了个球的\n");
//append_arr(&arr, 7);
show_arr(&arr);//输出
inversion_arr(&arr);//倒置
show_arr(&arr);//输出
sort_arr(&arr);//排序
show_arr(&arr);//输出
return 0;
}
void init_arr(struct Arr* parr,int len) //初始化结构体
{
//parr->len=99;
parr->pBase = (int*)malloc(sizeof(int) * len);
if (NULL == parr->pBase)
{
printf("动态内存分配失败");
exit(-1); //终止整个程序
}
else
{
parr->cnt = 0;
parr->len = len;
}
return;
}
void show_arr(struct Arr* parrshow) //输出数组
{
if (is_empty(parrshow))
printf("数组为空\n");
else
{
//printf("%d %d %s", parrshow->cnt, parrshow->len, parrshow->pBase);
for (int i = 0; i < parrshow->cnt; ++i)
{
//printf("%d", *(parrshow[i].pBase));
printf("%d\t", (parrshow->pBase)[i]);
//printf("%d", parrshow->pBase[i]);--ok
}
}
printf("\n");
}
bool is_empty(struct Arr* parrempty)//判断是否为空
{
if (0 == parrempty->cnt)
return true;
else
return false;
}
bool append_arr(struct Arr* parr, int val)//往数组中追加数据
{
//满时返回false
if (is_full(parr))
return false;
else//不满时追加
{
parr->pBase[parr->cnt] = val;
parr->cnt ++;
return true; //表示往里面添加元素成功
}
}
bool is_full(struct Arr* parr)//判断数组是否满
{
//不够好的代码
//if (parr->cnt == parr->len)
// return true;
//else
// return false;
return(parr->cnt == parr->len);
}
bool insert_arr(struct Arr* parr, int pos, int val)
{
if (is_full(parr) || pos<1 || pos>parr->cnt+1) //
return false;
else
{
int i;
for (i = parr->cnt - 1;i>=pos-1;--i)
{
parr->pBase[i+1] = parr->pBase[i];
}
parr->pBase[pos - 1] = val;
parr->cnt++;
return true;
}
}
bool delete_arr(struct Arr* parr, int pos, int* pval)
{
if (is_empty(parr) || pos<1 || pos>parr->cnt)
return false;
else
{
*pval = parr->pBase[pos - 1];
for (int i = pos; i < parr->cnt; ++i)
{
parr->pBase[i - 1] = parr->pBase[i];
}
parr->cnt--;
return true;
}
}
void inversion_arr(struct Arr* parr)
{
int i = 0;
int j = parr->cnt - 1;
int t;
while (i < j)
{
t = parr->pBase[i];
parr->pBase[i] = parr->pBase[j];
parr->pBase[j] = t;
++i;
--j;
}
return;
}
//冒泡排序的三种写法(实质两种)
void sort_arr(struct Arr* parr)
{
int i, j,t;
for (i = 0; i < parr->cnt-1; ++i)
{
for (j = i+1; j <= parr->cnt-1;++j)
{
if (parr->pBase[i] > parr->pBase[j])
{
t = parr->pBase[i];
parr->pBase[i] = parr->pBase[j];
parr->pBase[j] = t;
}
}
}
}
//void sort_arr(struct Arr* parr)
//{
// int i, j, t;
// for (i = 0; i < parr->cnt - 1; ++i)
// {
// for (j = i; j < parr->cnt - 1-i; ++j)
// {
// if (parr->pBase[i] > parr->pBase[j+1])
// {
// t = parr->pBase[i];
// parr->pBase[i] = parr->pBase[j+1];
// parr->pBase[j+1] = t;
// }
// }
// }
//}
//void sort_arr(struct Arr* parr)
//{
//int i, j, t;
// for (i = 0; i < parr->cnt - 1; ++i)
//{
// for (j = 0; j < parr->cnt - 1 - i; ++j)
// {
// if (parr->pBase[j] > parr->pBase[j + 1])
// {
// t = parr->pBase[j];
// parr->pBase[j] = parr->pBase[j + 1];
// parr->pBase[j + 1] = t;
// }
// }
//}
//}