连续存储数组的算法--初始化,输出,插入,追加,删除,倒置,排序

include <stdio.h>

include <malloc.h>

include <stdlib.h> //包含了exit函数

//c语言中没有bool类型,只有c++里面有

//定义了一个 struct Arr数据类型,里面包含三个成员变量。用来描述数组
struct Arr
{
int * pBase; //存放数组的首地址
int len; //数组所能容纳的元素的最大个数
int cnt; //当前数组的有效元素的个数
};

void init_arr(struct Arr *pArr,int length); //初始化
void show_arr(struct Arr *pArr); //输出
bool is_empty(struct Arr *pArr);//判空
bool is_full(struct Arr *pArr); //判满
bool append_arr(struct Arr *pArr,int val); //追加
bool insert_arr(struct Arr *pArr,int pos,int val); //插入,向某个位置前面插入,pos从一开始
bool delete_arr(struct Arr *pArr,int pos,int * pVal);

void sort_arr(struct Arr *pArr);
void inversion_arr(struct Arr *pArr);

int main(void)
{
struct Arr arr; //定义了struct Arr类型的变量 arr
int val; //要对arr变量进行操作,此时pBase,len,cnt里面都是垃圾数字
init_arr(&arr,6); //把arr的地址和长度传给形参,形参中的length用来接收长度,以便完成初始化
//printf("%d\n",arr.len);

show_arr(&arr);

append_arr(&arr,1);   //告诉函数要对哪个变量进行操作,和每次操作需要插入的值为多少
append_arr(&arr,3);
append_arr(&arr,4);
append_arr(&arr,5);
if(delete_arr(&arr,1,&val))//通过形参修改了val的值
{
	printf("删除成功\n");
}
else
{
	printf("删除失败\n");
}

/*append_arr(&arr,2);
append_arr(&arr,3);
append_arr(&arr,4);
append_arr(&arr,5);
append_arr(&arr,6);
insert_arr(&arr,2,12);
if(append_arr(&arr,0))
{
	printf("追加成功\n");
}
else
{
	printf("追加失败\n");
}*/


show_arr(&arr);

inversion_arr(&arr);
show_arr(&arr);
sort_arr(&arr);
show_arr(&arr);



return 0;

}
/*
初始化函数的编写思路:
1.在主函数中调用初始化函数,需要给其传参(传地址,传长度),以便让初始化函数知道要给对哪个变量进行初始化
2.对变量中的每个成员进行初始化
int *类型的pBase,使用malloc函数向内存为其申请空间
申请完毕后要看内存是不是分配给该成员变量一个空间,要使用if语句,如果失败则直接结束整个函数
如果成功,则对长度len 和有效长度 cnt进行初始化
3.如何找到变量中的那些成员呢?
需要使用指针,
pArr->pBase :pArr所指向的变量的pBase成员 pArr->pBase ==(*pArr).pBase ==arr.pBase
*/
void init_arr(struct Arr *pArr,int length)
{
pArr->pBase = (int *)malloc(sizeof(int)*length); //为pArr所指向的变量的pBase成员向内存申请空间,(int *)代表这块内存将来要存储的数据类型,malloc函数内的代表分配的大小;
if(pArr->pBase == NULL)
{
printf(“动态内存分配失败!”);
exit(-1); //终止整个程序
}
else
{
pArr->len = length; //把从实参传入的数值6传给pArr所指向的变量的len成员
pArr->cnt = 0; //给pArr所指向的变量的cnt成员设置初值,刚开始有效长度为0.
}
return; //void类型无返回值,return代表整个函数结束
}

bool is_empty(struct Arr *pArr)
{
if(pArr->cnt == 0)
{
return true;
}
else
{
return false;
}
}

bool is_full(struct Arr *pArr)
{
if(pArr->cnt == pArr->len) //有效长度等于数组长度时数组已满不能再追加值
{
return true;
}
else
{
return false;
}
}

/*
输出数组函数编写思路:
首先要想到数组是否为空的情况,因此
1.判断数组是否为空(如何判断数组为空呢?需要另外编写一个判空函数)
2.如果为空则输出语句—数组为空
3.如果不为空则输出数组的内容,根据数组的首地址找到数组的所有内容,注意此时的i应该小于其有效长度,因为输出的肯定是有效的内容。
4.编写一个函数时先把其思路写下来,后期如果需要调用其他函数则再去编写
5.编写判空函数:
判断其有效长度是否为零,为零则为空返回真,因为函数起到的作用就是判断是否为空,为空时当然要返回真,否则返回假(这里需要注意C语言中没有bool类型,c++中有)

*/

void show_arr(struct Arr *pArr)
{
if(is_empty(pArr)) //传入结构体变量的地址,pArr已经是arr的地址,所以只需要写pArr
{
printf(“数组为空\n”);
}
else
{
for(int i=0;i<(pArr->cnt);i++)
{
printf("%d ",pArr->pBase[i]);

	}
	printf("\n");
}

}

/*
看懂一个程序的三个步骤
1.流程
2.每个语句功能
3.试数
/
/

追加函数编写思路:
1.明确需要给函数传递什么内容(arr地址和追加的值)
2.再判断是否已满,满了则不能再追加
3.如果没有满,如何追加呢?
pArr->pBase[0]=1;
pArr->pBase[1]=2;
pArr->pBase[2]=3; //到这里有效长度为三,如果需要再往里面追加的话,则下一个值的下标为3,正好与有效长度的值相等
pArr->pBase[pArr->cnt]=val
追加结束以后有效长度也变了,加了一个,因此cnt++

*/
bool append_arr(struct Arr *pArr,int val) //追加函数,向末尾添加值 pArr用来接收arr的地址,val接收需要添加的值
{
if(is_full(pArr))
{
return false;
}

	pArr->pBase[pArr->cnt] = val; //cnt的值代表新加入元素的下标
	(pArr->cnt)++;				  //有效长度加一
	return true;

}

/*
编写插入函数的思路
1.首先确定传入哪些参数–地址,在那个位置插入,插入的值是多少(实参所需要),形参中定义接收这些值的变量即可
2.插入时要把插入位置之后(包括该插入位置)的所有元素往后移,因此需要使用for循环,i的值从有效长度-1开始,一直到pos-1,i>=pos-1 i–
3.把元素后移,把第i个下标的值,赋给第i+1个下标
4.把要插入的元素赋给要插入的位置的下标 pos-1
5.有效长度加一
6.这些步骤结束后要考虑该函数还存在哪些非正常情况(函数已满时要怎么办?输入的位置为负值或者超过他的有效长度+1时要怎么办)
7.解决上述两个问题,使用is_full函数和使用if函数判断pos的值

*/
bool insert_arr(struct Arr *pArr,int pos,int val)
{
if(is_full(pArr)) //判断是否已满
{
return false;
}
if(pos<1 ||pos>pArr->cnt+1) //pos的大小要在合理范围内
{
return false;
}
for(int i= pArr->cnt-1;i>=pos-1;i–)
{
pArr->pBase[i+1] = pArr->pBase[i]; //元素后移

}
pArr->pBase[pos-1] = val;   //把val的值插入到要插入的位置
(pArr->cnt)++;				//有效长度加一
return true;

}
/*
编写删除函数思路
1.首先确定需要传什么参数–地址,删除元素的位置,最后还要把删除元素的值返回(要定义一个int val,来接收元素)
2.然后判断是不是为空,空了就没有要删除的元素
3.pos的值在合理的范围内,pos不能小于1,不能大于有效长度
4.再删除之前要把要删除的值赋给pVal,一旦进行下面的操作就是在删除元素,无法再把需要返回给函数的值返回
5.把删除元素后面的元素需要往前移,i初始为pos,i要小于他的有效长度时,i++
6.因为是往前移所以下标为i的值赋值给了下标为i-1的值
7.删除以后有效长度减一
*/

bool delete_arr(struct Arr *pArr,int pos,int * pVal)
{
if(is_empty(pArr)) //判断是否是空,空了无法删除
{
return false;
}
if(pos<1 ||pos>pArr->cnt) //pos的大小要在合理范围内
{
return false;
}
*pVal = pArr->pBase[pos-1];
for(int i=pos;icnt;i++)
{
pArr->pBase[i-1] = pArr->pBase[i];
}
pArr->cnt–;
return true;
}

/*
倒置实现思路:
1.形参中的pArr用来接收arr的地址
2.定义i,j,代表从两头开始的数组下标,i从0开始,j从有效长度-1开始;t代表临时变量
3.循环条件i<j时,把元素互换
4.i++,j–
*/

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;

}

/*
排序实现思路
1.定义了两个数组下标,比较相邻的两个的大小,因此j=j+1
2.如果i下标的元素>j,则把i下标的元素值赋给j;
*/
void sort_arr(struct Arr *pArr)
{
int i,j,t;
for(i=0;icnt;i++)
{
for(j=i+1;jcnt;j++)
{
if(pArr->pBase[i]>pArr->pBase[j])
{
t = pArr->pBase[i];
pArr->pBase[i] = pArr->pBase[j];
pArr->pBase[j] = t;

		}
		
	}
}

}

/*
int main(void)
{
struct Arr arr; //定义了struct Arr类型的变量 arr
//要对arr变量进行操作,此时pBase,len,cnt里面都是垃圾数字
init_arr(arr);
printf("%d\n",arr.len);

return 0;

}

void init_arr(struct Arr array)
{
array.len = 99;
}

//注意:这样写不会改变实参的值,只会改变形参的值
*/
插入功能的思路
(此为观看完郝斌老师的数据结构的个人分析!)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值