数据结构之顺序表实现

顺序表:

线性表的顺序存储结构是一种随机存取的存储结构。顺序表存储结构容易实现随机存取线性表的第 i 个数据元素的操作,但在实现插入、删除的操作时要移动大量数据元素,所以,它适用于数据相对稳定的线性表,如职工工资表、学生学籍表等

顺序表插入,删除操作的时间复杂度

设pi是在第i个元素之前插入一个元素的概率,则在长度为n的线性表中插入一个元素时所需移动元素次数的平均次数为:
E 1 = i = 1 n + 1 p i ( n i + 1 ) E1=\displaystyle\sum_{i=1}^{n+1} pi(n-i+1)
设qi是删除第i个元素的概率,则在长度为n的线性表中删除一个元素所需要移动元素次数的平均次数为:
E 2 = i = 1 n q i ( n i ) E2=\displaystyle\sum_{i=1}^{n} qi(n-i) = n 1 2 \frac{n-1}{2}
假设在线性表中任意位置上插入和删除元素的概率都是相等的
p i = 1 n + 1 pi=\frac{1}{n+1}      q i = 1 n qi=\frac{1}{n}
由上可得:
E 1 = n 2 E1=\frac{n}{2}      E 2 = n 1 2 E2=\frac{n-1}{2}
若表长为n则删除和插入的时间复杂度为O(n)。

顺序表相关操作代码实现

下列代码中涉及到与顺序表相关的基本操作,包括:删除(包含了数组和指针两种实现),插入(包含了数组和指针两种实现),求前驱,求后继,翻转,排序,在尾部追加元素,初始化,销毁,置空等基本操作,还包括: 顺序表的无序和有序合并等拓展操作,以及相关的主函数测试。

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

#define LIST_INIT_SIZE 6	//要申请多少个数组元素空间
#define	LIST_INCREMENT 2	//当存储空间已满时,需要增加的元素空间个数

typedef struct Array
{
	int *base;	//相当于数组元素首地址
	int cnt;	//数组元素的有效个数
	int length;	//数组元素的长度
}ARR,*PARR;

//基本操作
int Length(PARR pArr);	//返回顺序线性表元素个数
void Init(PARR pArr);	//线性表顺序存储的初始化
void Destroy(PARR pArr);//销毁顺序线性表
void Clear(PARR pArr);	//置空顺序线性表
void Reverse(PARR pArr);//翻转
void Traverse(PARR pArr);	//遍历数组
void Sort(PARR pArr);	//排序
void append(PARR pArr,int e);	//追加e元素到数组的尾部
bool Empty(PARR pArr);	//判断顺序线性表是否为空
bool Get(PARR pArr,int i,int *e);//用e返回第i个数据元素的值
bool Prior(PARR pArr,int cur_e,int *pre_e);//用pre_e存储cur_e的前驱
bool Next(PARR pArr,int cur_e,int *next_e);//用next_e存储cur_e的后继
bool Insert(PARR pArr,int i,int e);	//在第i个元素之前插入元素e
bool Delete(PARR pArr,int i,int *e);//删除第i个位置的元素,并用e存储删除的元素

//拓展操作
void Union(PARR La,PARR Lb);//将所有在线性表Lb中但不在La中的数据元素插入到La中
/*
已知线性表La和Lb中的数据元素按值非递减排列
归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列
*/
void MergeList(PARR La,PARR Lb,PARR Lc);

int main()
{
	ARR arr;	//定义线性顺序表arr
	int val;
	Init(&arr);	//初始化线性顺序表
	append(&arr,1);	//向线性顺序表中添加元素
	append(&arr,8);
	append(&arr,11);
	append(&arr,6);
	append(&arr,9);
	append(&arr,4);
	printf("测试追加函数,追加6个元素后:");
	Traverse(&arr);
	append(&arr,10);
	append(&arr,7);
	printf("测试追加函数,追加8个元素后:");
	Traverse(&arr);
	Sort(&arr);
	printf("测试排序函数,排序后的元素为:");
	Traverse(&arr);
	if(Get(&arr,10,&val))
		printf("测试Get函数,第四个元素为:%d\n",val);
	else
		printf("测试Get函数,您要返回的元素不存在!\n");
	Reverse(&arr);
	printf("测试翻转函数,翻转后的元素为:");
	Traverse(&arr);
	if(Insert(&arr,2,99))
		printf("测试插入函数指针实现,插入成功!\n");
	else
		printf("测试插入函数指针实现,插入失败!");
	Traverse(&arr);

//	if(Insert(&arr,2,101))
//		printf("测试插入函数数组实现,插入成功!\n");
//	else
//		printf("测试插入函数数组实现,插入失败!");
//	Traverse(&arr);

	//if(Delete(&arr,4,&val))
	//	printf("测试删除函数指针实现,您删除的元素是%d\n",val);
	//else
//		printf("测试删除函数指针实现,您删除的元素不存在!\n");
//	Traverse(&arr);
	if(Delete(&arr,0,&val))
		printf("测试删除函数数组实现,您删除的元素是%d\n",val);
	else
		printf("测试删除函数数组实现,您删除的元素不存在!\n");
	Traverse(&arr);
	printf("测试Length函数,当前有效元素个数为%d\n",Length(&arr));
	if(Prior(&arr,6,&val))
		printf("测试前驱函数,6的前驱元素是%d\n",val);
	else
		printf("测试前驱函数,查询失败!\n");
	if(Next(&arr,6,&val))
		printf("测试后继函数,6的后继元素是%d\n",val);
	else
		printf("测试后继函数,查询失败!\n");
	Clear(&arr);
	Traverse(&arr);
	if(Empty(&arr))
		printf("测试是否为空, 空\n");
	else
		printf("测试是否为空, 非空\n");
	Destroy(&arr);
	printf("销毁顺序表!\n");
		ARR La,Lb,Lc;
	Init(&La);
	Init(&Lb);
	Init(&Lc);
	append(&La,3);
	append(&La,5);
	append(&La,8);
	append(&La,11);
	append(&Lb,2);
	append(&Lb,6);
	append(&Lb,8);
	append(&Lb,9);
	append(&Lb,11);
	append(&Lb,15);
	append(&Lb,20);
/*	printf("线性表La的元素为:");
	Traverse(&La);
	printf("线性表Lb的元素为:");
	Traverse(&Lb);
	Union(&La,&Lb);
	printf("LaULb=");
	Traverse(&La);
*/
	MergeList(&La,&Lb,&Lc);
	Traverse(&Lc);
	return 0;
}
int Length(PARR pArr)
{
	return pArr->cnt;
}
void Init(PARR pArr)
{
	pArr->base=(int *)malloc(LIST_INIT_SIZE*sizeof(int));//申请大小为LIST_INIT_SIZE的数组元素空间
	if(NULL==pArr->base)
		exit(-1);		//动态分配内存失败,退出程序
	pArr->cnt=0;		//初始有效元素个数为0
	pArr->length=LIST_INCREMENT;	//数组元素的长度为申请的长度
}
void Destroy(PARR pArr)
{
	free(pArr->base);//释放base所指向的已经申请的元素的空间
	pArr->base=NULL;//防止产生野指针,乱指向
	pArr->cnt=0;	//将有效元素个数和长度置为0
	pArr->length=0;
}
void Clear(PARR pArr)
{
	pArr->cnt=0;	//将有效元素个数置为0,其他不变
}
void Reverse(PARR pArr)
{
	int *p=pArr->base;
	int *q=pArr->base+pArr->cnt-1;
	int temp;
	while(p<q)
	{
		temp=*p;
		*p=*q;
		*q=temp;
		p++;
		q--;
	}
}
void Traverse(PARR pArr)
{
	if(Empty(pArr))
	{
		printf("数组内容为空\n");
	}
	else
	{
		for(int i=0;i<pArr->cnt;i++)
		{
			printf("%d ",pArr->base[i]);
		}
		printf("\n");
	}
}
void Sort(PARR pArr)
{
	int i,j,temp;
	for(i=0;i<pArr->cnt-1;i++)
	{
		for(j=i+1;j<pArr->cnt;j++)
		{
			if(pArr->base[i]>pArr->base[j])
			{
				temp=pArr->base[i];
				pArr->base[i]=pArr->base[j];
				pArr->base[j]=temp;
			}

		}
	}
}
void append(PARR pArr,int e)
{
	int *newbase=NULL;
	if(pArr->cnt>=pArr->length)		//当前存储空间已满,增加分配
	{
		newbase=(int *)realloc(pArr->base,(pArr->length+LIST_INCREMENT)*sizeof(int));
		if(NULL==newbase)
		{
			printf("动态内存分配失败!\n");
			exit(-1);	//分配空间失败,退出程序
		}

		pArr->base=newbase;	//新的数组元素首地址
		pArr->length+=LIST_INCREMENT;
	}
	pArr->base[pArr->cnt]=e;
	pArr->cnt++;	//有效元素个数加一
}
bool Empty(PARR pArr)
{
	if(pArr->cnt==0)
		return true;
	else
		return false;
}
bool Get(PARR pArr,int i,int *e)
{
	if(i<1||i>pArr->cnt)
		return false;
	*e=pArr->base[i-1];	//或者*e=*(pArr->base+i-1)
	return true;
}
bool Prior(PARR pArr,int cur_e,int *pre_e)
{
	//求前驱元素,用pre_e存储cur_e的前驱元素
	int i=2;
	int *p=pArr->base+1;
	while(i<=pArr->cnt&&*p!=cur_e)
	{
		i++;
		p++;
	}
	if(i>pArr->cnt)
		return false;
	*pre_e=*(p-1);
	return true;
}
bool Next(PARR pArr,int cur_e,int *next_e)
{
	//求后继元素,用next_e存储cur_e的后继元素
	int i=1;
	int *p=pArr->base;
	while(i<pArr->cnt&&*p!=cur_e)
	{
		i++;
		p++;
	}
	if(i==pArr->cnt)
		return false;
	*next_e=*(p+1);
	return true;
}
bool Insert(PARR pArr,int i,int e)
{
	int *newbase,*p,*q;
	if(i<1||i>pArr->cnt+1)			//判断i值是否合法
		return false;
	if(pArr->cnt>=pArr->length)		//当前存储空间已满,增加分配
	{
		newbase=(int *)realloc(pArr->base,(pArr->length+LIST_INCREMENT)*sizeof(int));
		if(NULL==newbase)
			exit(-1);	//分配空间失败,退出程序
		pArr->base=newbase;	//新的数组元素首地址
		pArr->length+=LIST_INCREMENT;
	}
	
	p=pArr->base+i-1;				
	for(q=pArr->base+pArr->cnt-1;q>=p;q--)
		*(q+1)=*q;
	*p=e;
	
	/*
		//数组实现:
		int k;
		for(k=pArr->cnt-1;k>=i-1;k--)
		{
			pArr->base[k+1]=pArr->base[k];	
		}
		pArr->base[i-1]=e;
	*/
	pArr->cnt++;	//有效元素个数加一
	return true;
}
bool Delete(PARR pArr,int i,int *e)
{
	int *p,*q;
	if(i<1||i>pArr->cnt)		//判断i值是否合法
		return false;
	/*
	p=pArr->base+i-1;
	*e=*p;
	for(q=pArr->base+pArr->cnt-1;p+1<=q;p++)
		*p=*(p+1);
	*/
	
		//数组实现:
		*e=pArr->base[i-1];
		int k;
		for(k=i-1;k<pArr->cnt-1;k++)
		{
			pArr->base[k]=pArr->base[k+1];	
		}
	pArr->cnt--;	//有效元素个数减一
}
void Union(PARR La,PARR Lb)
{
	//将所有在线性表Lb中但不在La中的数据元素插入到La中
	int i,j,val,flag;
	for(i=1;i<=Lb->cnt;i++)
	{
		flag=0;
		Get(Lb,i,&val);
		for(j=0;j<La->cnt;j++)
		{
			if(val==La->base[j])
			{
				flag=1;
				break;
			}
		}
		if(flag==0)
		{
			append(La,val);
		}
	}
}
void MergeList(PARR La,PARR Lb,PARR Lc)
{
	//已知线性表La和Lb中的数据元素按值非递减排列
	//归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列
	int i=1,j=1,va,vb;
	while(i<=La->cnt&&j<=Lb->cnt)
	{
		Get(La,i,&va);
		Get(Lb,j,&vb);
		if(va<=vb)
		{
			append(Lc,va);
			i++;
		}
		else
		{
			append(Lc,vb);
			j++;
		}
	}
	while(j<=Lb->cnt)
	{
		Get(Lb,j,&vb);
		append(Lc,vb);
		j++;
	}
	while(i<=La->cnt)
	{
		Get(La,i,&va);
		append(Lc,va);
		i++;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42447402/article/details/85459175
今日推荐