数据结构(C语言)——1线性表:顺序存储和基本操作

本文介绍了线性表的顺序存储结构,重点讲解了删除和插入操作。删除操作只需覆盖元素,不需释放内存;插入操作通过挪动元素完成。对于去除多个元素,文中提出了重构法,通过动态调整数组元素,实现了有效删除。理解数组元素存在形式是掌握顺序存储的关键。

趁着复习把课上的作业和代码上传上来嘿嘿嘿,这个系列的代码都是自己写的或者老师教学用的可能内存管理上有点小瑕疵,但是算法理解还是不错的!本系列所有代码在dev-cpp上可以跑通~

线性表的链式存储和基本操作:

#include <stdio.h>

const int maxn = 10000;

int m;  //命令数 
int n;  //线性表中元素个数 
int a[maxn];

void insert(int i, int x){//插入x到a[i] 
	for(int j=n;j>i-1;j--){
		a[j]=a[j-1];
	}
	a[i-1]=x;
	n++;
} 

void deleteByIndex(int i){ //删除a[i] 
	for(int j=i-1;j<n-1;j++){
		a[j]=a[j+1];
	}
	n--;
} 

void find(int x){//查找第一个x 
	for(int j=0;j<n;j++){
		if(x==a[j]){
			printf("%d\n",j+1);
			return;
		}
	}
	printf("0\n");
}

void eliminateRepeat(){ //去除重复元素
	int j=0;
	while(j<n-1){
		int k=j+1;
		for(int i=j+1;i<n;i++){
			if(a[i]!=a[j]){
				if(k!=i){
					a[k++]=a[i];
				}
				else{
					k++;
				}
			}
		}
		n=k;
		j++;
	}
}

void count(int x, int y){//统计[x,y]中元素个数	
	int t=0;
	for(int j=0;j<n;j++){
		if(a[j]<=y&&a[j]>=x){
			t++;
		}
	}
	printf("%d\n",t);
}

void deleteByRange(int x, int y){ //去除[x,y]范围内的元素 
	int k=0;
	for(int j=0;j<n;j++){
		if(a[j]<x&&a[j]>y){
			if(j!=k){
				a[k++]=a[j];
			}
			else{
				k++;
			}
		}
	}
	n=k;
} 

int main() {
	scanf("%d", &m);
	for (int k = 0; k < m; k++){
		int c, i, x, y;
		scanf("%d", &c);
		switch (c){
			case 2: scanf("%d", &i); deleteByIndex(i); break;
			case 3: scanf("%d", &x); find(x); break;
			case 4: scanf("%d%d", &x, &y); count(x, y); break;
			case 5: eliminateRepeat(); break;
			case 6: scanf("%d%d", &x, &y); deleteByRange(x, y); break;
		}
	}
	return 0;
}

这里比较难理解的是删除及插入等相关操作:

首先,说一下删除操作:

void deleteByIndex(int i){ //删除a[i] 
	for(int j=i-1;j<n-1;j++){
		a[j]=a[j+1];
	}
	n--;
} 

删除一个元素在顺序存储结构中不需要说把内存清空,只需要不用他的内容或者把他的内容覆盖掉就好了(可以参考选择排序),怎么覆盖呢,就直接把后面的一个元素覆盖上要删掉的元素,然后又空出一个位置,也要往前覆盖……直到最后一个覆盖上倒数第二个,然后数量减少1。

其次,再来说一下插入操作:

void insert(int i, int x){//插入x到a[i] 
	for(int j=n;j>i-1;j--){
		a[j]=a[j-1];
	}
	a[i-1]=x;
	n++;
} 

也是可以先通过插入排序了解一下数组让出一个元素不用不用分配内存,就把位置挪出来就好了,这里就从最后一个位置往后挪移个,一直到把要插入的位置挪动到插入的位置的后一个,就完成了,当然最后要将数量加1。

再来就是去除多个元素,比如这里的去除范围的元素:

void deleteByRange(int x, int y){ //去除[x,y]范围内的元素 
	int k=0;
	for(int j=0;j<n;j++){
		if(a[j]<x&&a[j]>y){
			if(j!=k){
				a[k++]=a[j];
			}
			else{
				k++;
			}
		}
	}
	n=k;
} 

其实方法有很多,主要是前移法和重构法,这里是重构法,思路很简单,就是找到不要的位置,因为是动态的,k记录的是现在实际的数组的大小,然后j是在原数组中的大小,注意重构不一定说一定要重新开出一块内存来,其实直接在原数组操作也可以:若j和k相同表示不用重构,直接pass,k和j不同的时候,把原来在j的位置放到了k然后就实现的重构(因为在计数的时候j跳过了要删除的元素,而k是”新”数组中j号元素的位置,所以就实现了正确重构),又因为j是动态的,所以出现多个要删除的也可以做到。

总的来说,顺序存储结构主要是要你理解这个数组的元素的存在形式把,初学的时候可能老会纠结删除或者添加元素就要把元素真的删掉或者真的添加一个位置,但其实只要让出来位置就好了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值