数据结构严蔚敏--顺序表增,删,改,合并顺序表

时隔一年,再一次打开了严奶奶的这本数据结构,事实证明这一年里还是有进步的,原因在于,我尽然能看懂这本书了,虽然与c语言交情不深,但是数据结构毕竟是凌驾于语言之上。

今儿个开始第一个---->顺序表的编辑
严奶奶的书上源码都有,因为是类c源码,所以有的写地方需要进行小小的改动,也给一年没有碰过指针的我上了一课o(╥﹏╥)o。如果有哪个大佬有一天能看见我发的这篇文章,有什么错误,还请批评指出。

1.头文件和状态码

头文件:

#include<stdio.h>
#include <stdlib.h>

函数结果状态码:
状态码在课本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; 

2.定义线性表的动态分配存储结构

由于线性表的长度可变,且所需的最大存储空间随问题的不同而不同,可以为其动态分配一维数组,代码如下有两种定义方法:

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;

3.初始化,构造空的线性表

这里想解释一下 (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;
}

到这里前戏完成

4.算法展示

算法不管是插入还是删除,还是线性表的合并,书上讲的都特别清楚,除了把源码拷过来之外,还想补充一点自己的小理解嘻嘻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++;  
}	

Main方法

张某人借鉴了大佬的输入(这里是真的不会了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]);
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值