时隔一年,再一次打开了严奶奶的这本数据结构,事实证明这一年里还是有进步的,原因在于,我尽然能看懂这本书了,虽然与c语言交情不深,但是数据结构毕竟是凌驾于语言之上。
今儿个开始第一个---->顺序表的编辑
严奶奶的书上源码都有,因为是类c源码,所以有的写地方需要进行小小的改动,也给一年没有碰过指针的我上了一课o(╥﹏╥)o。如果有哪个大佬有一天能看见我发的这篇文章,有什么错误,还请批评指出。
头文件:
#include
#include
函数结果状态码:
状态码在课本P10有提到
其中的ElemType和Status相当于给整型int起了个别名,和int的作用一模一样
#define LIST_INIT_SIZE 100 //初始分配量
#define LISTINCREMENT 10 //分配增量
#define OVERFLOW -1 //状态码
#define OK 1;
#define ERROR -1;
typedef int ElemType;
typedef int Status;
由于线性表的长度可变,且所需的最大存储空间随问题的不同而不同,可以为其动态分配一维数组,代码如下有两种定义方法:
1,结构体标签命名,
此时的SqList可以去声明新的结构体变量,如之后源码中的SqList La
struct SqList
{
ElemType *elem; //相当于定义int类型的elem指针
int length;
int listsize; //以sizeof(ElemType)为单位
};
2,也可以用typedef创建新类型,
此时的SqList可以去声明新的结构体变量,如之后源码中的SqList La
typedef struct
{
ElemType *elem; //相当于定义int类型的elem指针
int length;//标记动态数组当前长度
int listsize; //以sizeof(ElemType)为单位
}SqList;
这里想解释一下 (ElemType*) malloc (LIST_INIT_SIZE * sizeof(ElemType)); 经过百度,他给出的解释是这样的:malloc 是用于分配指定size的内存的库函数
将L.elem这个指针指向一块通过malloc函数分配的内存的地址,这个内存的大小为 sizeof(ElemType)*LIST_INIT_SIZE 的乘积这么大。
我想补充的是 sizeof(ElemType) 为int在内存中所占的字节数,因为ElemType(int)类型,所以 sizeof(ElemType) 作为基本单位出现
Status InitList(SqList &L){
//构造一个空的线性表
//malloc 是用于分配指定size的内存的库函数
//将L.elem这个指针指向一块通过malloc函数分配的内存的地址
//这个内存的大小为sizeof(ElemType)*LIST_INIT_SIZE的乘积这么大
//sizeof(ElemType)为int在内存中占用的字节数
L.elem = (ElemType*) malloc (LIST_INIT_SIZE * sizeof(ElemType));
if(!L.elem){
exit(OVERFLOW);
}
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return OK;
}
到这里前戏完成
算法不管是插入还是删除,还是线性表的合并,书上讲的都特别清楚,除了把源码拷过来之外,还想补充一点自己的小理解嘻嘻O(∩_∩)O。
下面的算法中有形参变量前添加了&,书本P10,这是借用了c++老大哥的引用调用的参数传递,会直接对实参进行处理,换句话说,传值引用一般就是生成一个临时对象,而引用调用是调用参数本身。但是区别于指针形参,值不能为null且不能更改指向的内存。
Status ListInsert(SqList &L, int i, ElemType e){
//在线性表第i个位置之前插入新的元素e
if(i<1 || i>L.length+1){
return ERROR;
}
if(L.length >= L.listsize){
ElemType *newbase = (ElemType*)
realloc (L.elem, (L.listsize+LISTINCREMENT) * sizeof(ElemType));
if(!newbase){
exit(OVERFLOW);
}
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
int *q = &(L.elem[i-1]);
//插入位置及之后的元素后移
for(int *p = &(L.elem[L.length-1]);p>=q;p--){
*(p+1) = *p;
}
*q = e;
L.length++;
return OK;
}
realloc函数,为线性表扩容。判断i的数值是否合法,以及插入位置及之后的元素后移书上都有详细解释。
这里一个地方耗了我好长时间 int *q = &(L.elem[i-1]); 还是不熟悉指针的原因吧,后来查了 菜鸟教程,才了解了大概,elem是int型指针, elem[数值-1] 就相当于 数组名[数值-1] 也相当与于 *(elem+数值) 遍历当前数组的第(数值)个元素,感觉以后还会范糊涂,先把此时的理解留在这里吧。
后面的没怎么钻牛角尖,理解起来相对顺畅一点,也相应的做了注释,不做过多的阐述了(其实就是懒)
/*
删除第i个元素
*/
Status ListDelete(SqList &L, int i, ElemType &e){
//删除第i个元素并用e返回其值
if(i<1 || i>L.length){
return ERROR;
}
//被删除元素位置
int *p = &(L.elem[i-1]);
e = *p;
//此时的表长度 elem基址后移Length-1位,指向表元素的最后一项
int *q = L.elem+L.length-1;
//删除位置之后的元素前移,覆盖前一项
for(*p;p<q;p++){
*p = *(p+1);
}
//表长度减一
L.length--;
return OK;
}
void ListUpdate(SqList &L, int i){
//修改第i个元素
L.elem[i-1] = i;
}
Status ListSelect(SqList &L, int num, int &index){
//查询第i是否存在,若存在则返回元素第一次出现所在下标,不存在返回-1
for(int i=0;i<L.length;i++){
if(L.elem[i] == num){
index = i;
return index;
}
}
return -1;
}
void MergeList(SqList &la, SqList &lb, SqList &lc){
int *p,*q; //p为a表 q为b表 。
int *pa,*pb,*pc;
pa = la.elem; pb = lb.elem;
lc.listsize = lc.length = la.length + lb.length;
pc = lc.elem = (ElemType *)malloc(lc.listsize * sizeof(ElemType));
if(!lc.elem)exit(OVERFLOW );
p = la.elem + la.length - 1;
q = lb.elem + lb.length - 1;
while(pa <= p && pb <= q)
{
if(*pa <= *pb) *pc++=*pa++;
else *pc++ = *pb++;
}
while(pb <= p) *pc++=*pa++;
while(pb <= q) *pc++=*pb++;
}
张某人借鉴了大佬的输入(这里是真的不会了o(╥﹏╥)o),so spisy,END。
main(){
SqList la,lb,lc;
InitList(la);
InitList(lb);
InitList(lc);
scanf("%d",&la.length);
for(int i=0;i<la.length;i++){
scanf("%d",&la.elem[i]);//这里elem虽然是int类型指针,但是初始化被分配空间,所以定义一个elem数组一样
}
scanf("%d",&lb.length);
for(int i=0;i<lb.length;i++){
scanf("%d",&lb.elem[i]);//这里elem虽然是int类型指针,但是初始化被分配空间,所以定义一个elem数组一样
}
MergeList(la, lb, lc);
//向La表的第三项插入数字100
// ListInsert(la, 3, 100);
//删除La表的第三项
// ElemType e;
// ListDelete(la, 3 , e);
// printf("被删除的元素-->%d\n",e);
//查询第i个元素,若存在则返回元素第一次出现所对应的下标,不存在返回-1
// ElemType index;
// ListSelect(la, 3, index);
// printf("查询元素的下标为-->%d\n",index);
printf("操作完成,此时的表内容为");
for(int i=0;i<lc.length;i++){
printf("%d ",lc.elem[i]);
}
}