前言
以下代码来自于郝斌老师数据结构视频,加以自己的理解作了注释,用于学习和复习,欢迎大家指正错误。
代码的运行环境:DEV-C++ 6.3版本,创建源文件为.cpp文件即可编译运行。
#include <stdio.h>
#include <stdlib.h>
//定义了一个数据类型,该数据类型含有三个成员
struct ARR{
int *pBase; //存储数组第一个元素的地址,可以通过下标遍历数组内的每一个元素
int len; //数组长度,最大元素个数
int cnt; //当前数组有效元素的个数
//int increment;//自动增长因子、牺牲部分内存,提高存储效率
};
/******************************************************************************************/
/**********---------------------------函数声明部分----------------------------*************/
/******************************************************************************************/
void init_arr(struct ARR *pArr,int length); //初始化顺序表
bool append_arr(struct ARR *pArr,int val); //追加数据
bool insert_arr(struct ARR *pArr,int pos,int val); //插入数据
bool delete_arr(struct ARR *pArr,int pos,int *pVal);//删除指定位置数据
//bool get();
bool is_empty(struct ARR *pArr); //判断数组是否空
bool is_full(struct ARR *pArr); //判断数组是否满
void sort_arr(struct ARR *pArr); //排序数组元素(升序排序)
void show_arr(struct ARR *pArr); //打印数组元素
void inversion_arr(struct ARR *pArr); //倒置元素函数(全部倒置)
int main(void){
struct ARR a;//尚未创建顺序表
int val;
init_arr(&a,7);//初始化7个数据空间的数组
//show_arr(&a);
append_arr(&a,1);
append_arr(&a,2);
append_arr(&a,3);
append_arr(&a,7);
insert_arr(&a,2,99);
show_arr(&a);
if(delete_arr(&a,3,&val)){
printf("删除成功!\n%d被删除\n",val);
}
else{
printf("删除失败!\n");
}
// insert_arr(&a,3,26);
// if(append_arr(&a,4))
// printf("追加成功\n");
// else
// printf("追加失败\n");
show_arr(&a);
inversion_arr(&a);
show_arr(&a);
sort_arr(&a);
show_arr(&a);
//printf("%d\n",a.len);
}
/******************************************************************************************/
/**********---------------------------函数定义部分----------------------------*************/
/******************************************************************************************/
//结构体变量不能加减乘除,但能相互赋值
/*-------------------------------------
函数功能:初始化数组,分配内存
参数:*pArr---指向结构体数组的指针,存放顺序表(数组)首地址
length---数组长度(分配内存大小)
完成动态内存分配
--------------------------------------*/
void init_arr(struct ARR *pArr,int length){
pArr->pBase = (int *)malloc(sizeof(int)*length);//分配失败malloc会给pBase一个NULL,成功会返回开辟空间的首地址
//如果动态分配失败,说明pBase是NULL
if(NULL == pArr->pBase){
printf("动态分配内存失败!\n");
exit(-1);//终止整个程序
}
else{
pArr->len = length;
pArr->cnt = 0;//线性表中有效元素个数为0
}
return;//无返回值是告知维护者函数到此终止
}
/*----------------------------------
函数功能:判断数组是否为空
参数:*pArr---指向结构体数组的指针,存放顺序表首地址
通过有效计数cnt来判断数组是否为空
----------------------------------*/
bool is_empty(struct ARR *pArr){
if(0 == pArr->cnt)
return true;
else
return false;
}
/*----------------------------------
函数功能:判断数组是否为满
参数:*pArr---
判断条件;有效计数cnt是否等于数组长度len
----------------------------------*/
bool is_full(struct ARR *pArr){
//此时说明分配的每个空间都被数据填满
if(pArr->cnt == pArr->len)
return true;
else
return false;
}
/*-------------------------------------
函数功能:打印数组内容
参数:*pArr---
-------------------------------------*/
void show_arr(struct ARR *pArr){//取地址操作,pArr已经是顺序表的地址了
if(is_empty(pArr))//这里填pArr?*pArr?&pArr?第二第三个不对,第二个是地址的指针,不对;第三个对地址再取地址,显然不对
{
printf("array is empty!\n");
}
else
{
for (int i=0;i<pArr->cnt;++i)
printf("%d ",pArr->pBase[i]);
printf("\n");
}
}
/*------------------------------------------
函数功能:在数组的最后一个有效元素后添加数据
参数:*pArr---
val---要添加的数据
-------------------------------------------*/
bool append_arr(struct ARR *pArr,int val){
if(is_full(pArr))//满返回false
return false;
//不满时追加
pArr->pBase[pArr->cnt] = val; //让结构体中的第cnt个指针地址赋值val
pArr->cnt++; //结构体中的cnt++有效个数自增一,不然添加元素不显示
return 0;
}
/*------------------------------------------------------
函数功能:插入数据
参数:*pArr---结构体指针
pos---插入位置
val---插入数据
注意:在插入数据的位置,
其后面的所有数据下标增1,移动顺序,末尾的数据先动,依次跟上
--------------------------------------------------------*/
bool insert_arr(struct ARR *pArr,int pos,int val){
int i;
if(is_full(pArr)){
return false;
}
if(pos<1||pos>pArr->cnt+1){//+1是因为pos可以设置有效位数的最后一位插入,显然是在数组没有满的前提下
return false;
}
for(i=pArr->cnt-1;i>=pos-1;--i){//在第pos个位置插入数据,对应数组下标pos-1
pArr->pBase[i+1] = pArr->pBase[i];
}//先移动,把插入位置的空间腾出来
pArr->pBase[pos-1] = val;//再赋值,完成数据插入
pArr->cnt++; //最后不要忘了有效个数的改变,不然插入一位就会丢失一位
return true;
}
/*--------------------------------------
函数功能:删除并返回被删除的数据
参数:*pArr---
pos---删除位置
*pVal---被删除的数据,返回到主函数
----------------------------------------*/
bool delete_arr(struct ARR *pArr,int pos,int *pVal){
int i;
if(is_empty(pArr)){//判断数组是否空,要删除的肯定不能是空数组
return false;
}
if(pos<1||pos>pArr->cnt){//删除的只能是已有数据,不能在有效计数外删除
return false; //这一点和插入有区别
}
//主函数中的实参val等价于pVal形参
*pVal = pArr->pBase[pos-1];//pos-1为要删除的数据数组下标
for(i=pos;i<pArr->cnt;++i){
pArr->pBase[i-1] = pArr->pBase[i];
}
pArr->cnt--;
//删除完之后数组有效个数-1,不然会有一个多余数据
return true;
}
/*---------------------------
函数功能:倒置元素(逆序输出)
参数:*pArr---
----------------------------*/
void inversion_arr(struct ARR *pArr){
int i=0;
int t=0;//中间变量用于过渡
int j = pArr->cnt-1;//最后一个有效值所在的数组下标
/*数组个数为奇数,交换到最后一位时i=j
数组个数为偶数,交换到最后一位时i>j
取退出循环的条件为i<j*/
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;
int t=0;
for(i=0;i<pArr->cnt;++i){
for(j=i+1;j<pArr->cnt;++j){
if(pArr->pBase[i]>pArr->pBase[j]){
t = pArr->pBase[i];
pArr->pBase[i] = pArr->pBase[j];
pArr->pBase[j] = t;
}
}
}
}