线性表(1)---顺序表

                         线性表(♪含C实现基本操作♪)

严老师《数据结构》一书中说提出的第一种结构就是线性表,这也正是因为它是数据结构中最简单的数据存储结构。

本篇就简单介绍相关的基本操作的原理及相应的C代码。                                                                                                                  

--------------------------------------基本原理和概念都懂的宝宝可以直接往下看代码----------------------------

线性表的存储结构
线性表的存储结构

 

顺序存储结构我们再熟悉不过了,比如数组;

而链式存储结构可更大程度的利用空间,通过指针记录下一个节点的地址,这样即使异地恋他们也不会迷失哈哈(如上图所示)。~这儿有链表蛤~------>https://blog.csdn.net/qq_38193883/article/details/93322720

因此用链式存储结构时定义线性表,需要利用结构体,里面记录数据,指针,为了方便操作,还需要记录线性表的长度与空间。

(不要慌张,先看看两者的区别)

长度lenth 与 空间的区别示意图

因此顺序存储时酱紫定义

//定义存储结构
	 typedef struct Link{
 	     int *elem;//表的基址
	 	 int number;//表的长度,即元素个数
	 	 int size;//表的空间
	 }List;

插入操作:                     (先看图意会下)

插入元素时的示意图

 

步骤: 先找到插入位置------>从插入位置开始,到最后一个元素为止,逐个后移-------->目标位置已经被腾空,放数据即可。

操作时应注意:移动时为了防止值被覆盖,要从尾部开始后移,把值赋值给后面的位置。(如果从插入位置开始正序后移的话,就错啦)

上核心代码(更详细的往下扒拉哈~):

//p为插入位置,rear为尾指针
for(rear;rear>=p;rear--)
		 {
		     *(rear+1)=*(rear);
	     } 
//此时rear已经移动到p的位置
 *p=data;//或者写*rear=data;

删除操作:

步骤:先找到删除位置-------->从删除位置开始,到左后一个元素为止,逐个前移

操作时:(注意与插入操作对比区别)正序前移即可,即从删除位置开始,赋值为它后面的值。

上核心代码(详细的在下面哦~):

//p为删除位置,rear为尾指针
for(p;p<rear;p++)
	{
		*(p)=*(p+1);//从删除位置p开始赋值为后面的值
    }

以下是一些一些常用的操作,及测试案例:

包括:

  1. 线性表的声明定义

  2. 线性表的插入,删除

  3. 线性表的清空,销毁

  4. 获取特定位置元素及前驱后继

  5. 两个线性表的合并

  6. 遍历输出

  7. 查找某元素在表中第一次(最后一次)出现的位置

                   //顺序表的基本操作
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define initsize 100 //初始空间分配量
#define increase  10 // 分配增量 
//线性表的相关操作(动态分配的顺序存储结构) 

	//定义存储结构
	 typedef struct Link{
 	     int *elem;
	 	 int number;
	 	 int size;
	 }List;
	 
//(1)创建一个空表(初始化)InitList(&L)
int InitList(List &L){
	L.elem=(int *)malloc(initsize*sizeof(int));//分配初始空间
	if(!L.elem){return -1;}
	L.number=0;//表内元素数目初始化为0  
	L.size=initsize;
	return 1;  
   }

//(2)销毁列表DestroyList(&L)
int DestroyList(List &L){
  	L.size=0;
  	L.number=0;
  	L.elem=NULL;
    //或直接free(&L);
	return 1;  
  }

//(3)清空列表ClearList(&L)
   bool ClearList(List &L)
  {
	if(L.number==0){
	printf("表已清空~\n"); 
	return true;//表内元素数目为0 
    }
	L.number=0; //否则将元素个数置为0 
	printf("ok!\n"); 
	return true;  
  }

//在表L的第pos个位置之前插入数据data 
   int 	Insert(List &L,int pos,int data)
   {
   	    //pos的合法位置是1~len+1;其中pos=1表示插头,pos=len+1表示插尾
	    if(pos<1||pos>L.number+1) return 0;//先判断插入位置的合法性 

        //还需判断空间是否充足 ,数据填满时需扩展空间再分配 
   	    if(L.number>=L.size)
   	    {
   	    	int *newid=(int *)realloc(L.elem,L.size+increase*sizeof(int));
   	        if(!newid) return 0;
			L.elem=newid;
			L.size+=increase;  	
        }
         int *p= &L.elem[pos-1];//p为表中插入位置,与用户默认值相差1; 
         int *rear=&L.elem[L.number-1];//rear为表中最后一个元素的位置;
		 //接下来从插入位置开始到最后一个元素为止逐个后移,腾出插入位置即L.elem[pos-1]放data; 
		 for(rear;rear>=p;rear--)
		 {
		     *(rear+1)=*(rear);
	     } 
	     *p=data;//其实这里也可以写*rear=data; 
	     L.number++;//插入后元素个数增加一
	     return 1;
   }
             
 //删除给定位置元素DeleteList(&L,pos,e)
int DeleteList(List &L,int pos,int &e)
{
	//也是先判断位置是否合理 :1=<pos<=L.number;
	if(pos<1||pos>L.number) return 0;
	int *p= &L.elem[pos-1];//p为表中要删除的位置,与用户默认值相差1; 
	e=*p;//先保存所删除的值 
	int *rear=&L.elem[L.number-1];//rear为表中最后一个元素的位置;
	//接下来从删除位置后一个开始到最后一个位置为止,逐个前移一位
	for(p;p<rear;p++)
	{
		*(p)=*(p+1);
    }
    L.number--;//删除后元素个数减少一
	return 1; 
}
             
//获取给定位置元素以及直接前驱直接后驱GetElem(L,i,&e)
int GetElem(List &L, int i, int &e,int &pri_e,int &next_e) {
  if(L.number==0){
        printf("抱歉,当前线性表是空表\n");
        return -1;
    }
    if(i<1 || i>L.number){
        printf("当前位置超出了线性表的范围\n") ;
        return -1;
    }
     pri_e=L.elem[i - 2]; 
	 e = L.elem[i - 1];
     next_e=L.elem[i];
    return 0;
}

//遍历输出
void print(List &L) {
    for (int i = 0; i < L.number; i++) { 
        printf("%d ",L.elem[i]);
    }
    printf("\n");
} 

       //查找某元素在表中第一出现的位置
	   //若想查看最后一次出现的位置只需将i倒序遍历即可 
int LocateList(List L,int e)
{
      int i=0;
	for(i;i<L.number;i++)
	{
		if(L.elem[i]==e)
		{
			return i+1; 
		}
	}
	if(i==L.number)
	{
	return -1;	
	}
}
 
//归并两表(不要求两表提前有序,且未去重) 
void MergeList(List La,List Lb,List &Lc)
{
	int *a=La.elem;
	int *b=Lb.elem;
	int *c=Lc.elem=(int *)malloc(initsize*sizeof(int));
	if(!Lc.elem){
		return ;
	}
	Lc.size=Lc.number=La.number+Lb.number;
	int *ar=a+La.number-1;//ar表示遍表a的尾指针 
	int *br=b+Lb.number-1;//br同理 
	while(a<=ar&&b<=br)
	{
		if(*a<=*b)
		{
			*c++ = *a++;
		}
		else{
			*c++ = *b++;
		}
	}//跳出循环可额能有两种情况:a或b提前遍历结束  ab都遍历结束 
	//则需把剩余的都加进c表中 
	while(a<=ar){
		*c++ = *a++;	
	}
	while(b<=br){
		*c++ = *b++;
	}
} 

//测试
int main()
{
	//声明表; 
	List La;
	List Lb;
	//初始化 
	InitList(La);
	InitList(Lb);
	
	//插入元素 
	printf("La的变化过程\n");
	for(int i=1;i<=5;i++)
	{
		Insert(La,i,2*i);
		print(La);
	}
	printf("Lb的变化过程\n");
	for(int i=1;i<=5;i++)
	{
		Insert(Lb,i,i-1);
		print(Lb);
	}
	
	//合并 
	List Lc;
	InitList(Lc);
	printf("\n合并La与Lb===>Lc表: \n");
	MergeList(La,Lb,Lc);
	print(Lc);
	
	
	//元素第一次出现的位置 
	printf("\n元素2在表Lc中第一次出现的位置是%d\n",LocateList(Lc,2));
	
	//查找前驱后继 
	int e,pri_e,next_e;
	GetElem(Lc,3,e,pri_e,next_e);
	printf("\n在表Lc中第三个位置的元素是%d,它前面是%d,后面是%d\n",e,pri_e,next_e);
	
	//删除元素 
	int del;
	DeleteList(Lc,5,del);
	printf("\n删除表Lc中第5个位置的元素%d\n",del);
	print(Lc);
	
	//清空 
	printf("\n清空LC\n"); 
    ClearList(Lc);
    print(Lc);
	return 0; 
 } 

测试结果展示(开心,蛤蛤~):

运行结果
俺的运行结果

正经致谢:-------->

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值