线性表-顺序表的简单知识

正在重新学数据结构,觉得算法和算法思想真的是很重要也是相融相通的。程序的具体完成只是时间给你的任务而已,理解了算法,然后根据你的算法思想一步一步的写出来,感觉很赞。记录下自己慢慢学习的过程,留着自己以后回来复习,也希望为那些和我一样一直很渣却迫切想要进步的人服务。

顺序表的结构其实就是一个数组的组成。数组有固定的长度,里面存了一些数据。然后有一个灰常重要的头指针

typedef struct list {
    datatype *pBase;//头指针
    int length;//数组长度
    int count;//当前已有个数
}Arr,*pArr;

其实我觉得数据结构里面最重要的就是怎么把一个结构用结构体给描述出来,栈,队列,二叉树我觉得都是一样的,利用这个结构就可以解决所有的相关问题(最基础根本的地基我觉得),而且如果你记住了或者理解了每种数据结构的构造,其实那些相关的操作才可能慢慢掌握了。

顺序表不算很难,基本原理就是数组,就不解释定义了。代码里面注释也很详细。

还有我觉得注释真的很重要,以前我写代码,写完了过了些天我在看就等于重新再写一遍一样,一点都没效率。

我认为一句代码该不该注释一是根据你自己的水平,就像你在二年级你就不会去注释1 + 1 = 2了,但你要是幼儿园,你可能还要加星号强调一下(前提你是个爱学习的好孩子)

二是你觉得你如果一眼看上去不太可能理解其意思,比如变量,我觉得就应该添上那多余的句话。

但是你的程序只是写的玩,没有保存的意思,就不需要了,草稿程序就不必那么规矩了。

下面是完整的程序,应该蛮详细的吧我觉着,基本的操作都有。

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

typedef int datatype;
//顺序实现其实就是数组的实现
typedef struct list {
	datatype *pBase;//头指针
	int length;//数组长度
	int count;//当前已有个数
}Arr,*pArr;

void InitList(pArr a,int length);//初始化数组
bool isEmpty(pArr a);//判断是否是空
bool isFull(pArr a);//判断是否已满
bool Append(pArr a,datatype item);//追加,就是在最后插入的意思
bool Insert(pArr a, int i, datatype  item); //在数插入到位置i
bool DeleteArr(pArr a, int i, datatype *item);//删除位置i上的数
void Traverse(pArr a);//遍历数组
void Inversion(pArr a);//翻转数组
void Clear(pArr a);//清空
void Destroy(pArr a);//释放空间
void jiao(pArr a, pArr b,pArr &c);//交集
void bing(pArr a, pArr b, pArr &c);//并集
void cha(pArr a, pArr b, pArr &c);//差集
//初始化数组
void InitList(pArr a,int length) {
	a->length = length;
	a->pBase = (datatype *) malloc(sizeof(datatype )*a->length);//建立数组的头指针
	if(!a->pBase ) {//判断是否分配空间
		printf("failed!\n");
		exit(-1);
	}
	a->count = 0;//初始化的数组长度是0,里面元素个数也是0
	return ;//程序的结束这样写蛮好的  我也是看郝斌老师那个视频学到的
}
//==========================================
//判断是否是空
bool isEmpty(pArr a) {
	if(0 == a->count) {//当前数组里面没元素就是空了哈
		printf("空!\n");
		return true;
	}else
		return false;
}
//==========================================
//判断是否已满
bool isFull(pArr a) {
	if(a->count == a->length ) {//数组元素和数组长度已经相等
		printf("满!\n");
		return true;
	}
	else
		return false;

}
//===========================================
//遍历数组
void Traverse(pArr a) {
	for(int i = 0 ; i < a->count; i++) {//可别写成a->length
		printf("%d ",a->pBase[i]);
	}
	printf("\n");
	return ;
}

//===========================================
//追加
bool Append(pArr a,datatype item) {
	  if(isFull(a))//肯定要先判断是否已满
		  return false;
	  a->pBase [a->count] = item;//数组从0开始 ,所以下标算算
	  a->count++;//记得当前个数加1啊
	  return true;
}

//========================================
//清空
void Clear(pArr a) {
	a->count = 0;//就是如此简洁
	return ;
}
//========================================
//释放空间
void Destroy(pArr a) {
	free(a->pBase);
	a->pBase = NULL;
	return ;
}

//===========================================
//在数插入到位置i
/*
	a b c d e 假如我要在第3个位置插入w(不想举整数数组,万一和下标搞混),意思翻译就是我把第三个位置上的c
	给挤到一边去了,自己做老三。(其实取决于你对插c前还是插c后的认知了哈)
	我想要插入一个数,那么要么把 a b 向左移动一个位置出来让给w,要么 c d e 向右移动一个位置让给w,显然采取
	后种,a b前面可是头指针啊

*/
bool Insert(pArr a, int i, datatype  item) {
	 if(isFull(a))//肯定要先判断是否已满
		 return false;
	 for(int n = a->count - 1; n >= i-1; n--) {//下表问题慢慢琢磨
		 a->pBase[n+1] = a->pBase[n];		
	 }
	 a->pBase[i-1] = item;//插入值
	 a->count++;//这一句千万别忘了 虽然遍历时候不会出错
	 return true;
}
//=========================================
//删除位置i上的数
/*其实和插入的道理差不多
	a b c d e 假如我要删除第三个位置上的c,其实就是把c之后的d e向左移动一个位置,然后count--就ok了

*/
bool DeleteArr(pArr a, int i, datatype &item) {
	if(isEmpty(a)) {
		return false;
	}
		printf("%d\n",a->count);
	item = a->pBase[i-1];
	for(int n = i; n <= a->count-1; n++) {
		a->pBase[n-1] = a->pBase[n];
	}
	a->count--;//当前个数减1

	return true;
	
}
//====================================
//翻转数组
/*
	意思很明了,就是把数组倒过来,其实可以理解为,前后相对的位置的呼唤,第一个位置和最后一个位置,
	第二个位置和倒数第二个位置
*/
void Inversion(pArr a) {
	int i = 0 ; 
	int j = a->count-1;
	while(i < j) {
		int temp = a->pBase[i];//交换位置
		a->pBase[i] = a->pBase[j];
		a->pBase[j] = temp;
		i++;//前面向前移动一个位置,后面向后移动一个位置
		j--;
	}
	return ;
}
//====================================
//元素是否存在数组中
bool Find(pArr a,datatype item) {
	for(int i = 0 ; i < a->count; i++) {
		if(item != a->pBase[i])
			continue;
		else
			return true;
	}
	return false;
}
//交集
/*
交集嘛,就是把俩个集合相同的元素放在一起
*/
void jiao(pArr a, pArr b,pArr c) {
//if用来判断哪个数组短点 不然假如a100 个数,b就1个数,a还要用100次去和b比较啊
	if( (a->count < b->count)) {//a比较短
		for(int i = 0 ; i < a->count; i++) {
			if( Find(b,a->pBase[i]) ) {//如果a中的数在b中也有
				c->pBase[c->count] = a->pBase[i];//c->pBase[c->count] c->count可不能写成i
				c->count++;
			}
		}
	}else {
		for(int i = 0 ; i < b->count; i++) {
			if( Find(a,b->pBase[i]) ) {//如果a中的数在b中也有
				c->pBase[c->count] = b->pBase[i];//c->pBase[c->count] c->count可不能写成i
				c->count++;
			}
		}
	
	}
		return ;
}
//======================================
//并集
/*
我没考虑 1 2 3 3和 1 2 4这种的并集是俩个3都要存么 我至算了一个 
*/
void bing(pArr a, pArr b, pArr c) {
	int i = 0; 
	int j = 0 ;
	while(i < a->count) {
		if(!Find(c,a->pBase[i])) {//如果该数不在c里面,就加进去,然后c-<count加1
			Append(c,a->pBase[i]);
		}
		i++;
	}
	while(j < b->count ) {//如果该数不在c里面,就加进去,然后c->count加1
		if(!Find(c,b->pBase[j] )) {
			
			Append(c,b->pBase[j]);
		}
		j++;
	}
	return ;

}
//========================================
//差集
/* 差集意思好像是把a中含有b中的元素去掉,就是把交集去掉吧*/
void cha(pArr a, pArr b, pArr c) {
	int i = 0; 

	while(i < a->count) {
		if(!Find(b,a->pBase[i])) {//如果a中的数不在b中里面,就加进去,然后c->count加1
			Append(c,a->pBase[i]);
		}
		i++;
	}
	return;
}
//==========================================
//测试程序
int main() {
	Arr a;
	InitList(&a, 5);
	Traverse(&a);
	printf("追加\n");
	Append(&a, 1);
	Append(&a, 2);
	Append(&a, 3);
	Append(&a, 4);
	Traverse(&a);
	printf("插入\n");
	Insert(&a, 3,33);
	Append(&a,5);
	Append(&a,9);
	Traverse(&a);
	int item = 0 ;
	printf("删除\n");
	DeleteArr(&a, 3,item);
	printf("删除的是:%d \n",item);
	Traverse(&a);
	printf("清空\n");
	//Clear(&a);
	//Traverse(&a);
	Append(&a,9);
	Traverse(&a);
	Inversion(&a);
	Traverse(&a);
	//交并差测试
	Arr a1,b,c;
	InitList(&a1,5);	
	Append(&a1,2);
	Append(&a1, 3);
	Append(&a1, 1);
	Append(&a1, 4);
	Append(&a1, 5);
	printf("遍历a1:");
	Traverse (&a1);
printf("=================\n");
	InitList(&b,4);
	Append(&b, 1);
	Append(&b, 5);
	Append(&b, 2);
	Append(&b, 0);
	printf("遍历b:");
	Traverse(&b);
printf("=================\n");
	InitList(&c,5);
	c.length = a1.length + b.length ;
	printf("交集\n");
	jiao(&a1,&b,&c);
	Traverse(&c);
	Clear(&c);//先把c给清空

	printf("并集\n");	
	bing(&a1,&b,&c);
	Traverse(&c);
	printf("=================\n");
	Clear(&c);//先把c给清空

	printf("差集\n");
	cha(&a1,&b,&c);
	Traverse(&c);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值