数据结构—线性表总结

本文深入探讨了顺序存储结构中的顺序表实现,包括初始化、插入、删除及元素获取操作,同时对比介绍了链式存储的单链表,涉及头节点、插入、删除和查找等关键操作。了解顺序表和链表的优缺点,适合初学者和进阶者阅读。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录 

线性表

顺序存储结构

顺序表

链式存储结构


线性表

定义:零个或多个数据元素的有限序列。

顺序存储结构

顺序表

1.顺序表存储结构

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

#define MAXSIZE 20  //线性表存储空间的初始分配量
#define OK 1    //成功标识
#define ERROR 0 //失败标识

typedef int Status;	//Status是函数的类型,其值是函数结果状态代码,如OK等

typedef int ElemType;   //ElemType的类型根据实际情况而定
//顺序表数据结构
typedef struct
{
    ElemType *elem;
    int length;
}SqList;

2、构造一个空的顺序表L

①申请空间

②判断申请是否成功

③L -> length = 0;//构造空顺序表

Status InitList(SqList* L){
    //构造一个空的线性表L
    L -> elem = (ElemType *)malloc(MAXSIZE*sizeof(ElemType));
    if(!L -> elem){
        return ERROR;
    }
    L -> length = 0;
    return OK;
}

3、顺序表的插入

操作目的:在L中的第i个位置之前插入新的数据元素e,L的长度加1

①传入顺序表SqList *L(要加*:因为该操作要改变顺序表),第i个位置,要插入的新元素e

②判断该线性表的是否还有空间

③判断i在不在顺序表范围内

④若插入位置不在表尾,要对第i个元素及其后面的元素都进行移位操作

⑤将新元素插入第i个位置

⑥长度加1

Status ListInsert(SqList *L, int i, ElemType e){
    int k;
    if (L->length == MAXSIZE){  //线性表没有剩余空间
        return ERROR;
    }   
    if (i < 1 || i > L->length+1){ //当i不在范围内时
        return ERROR;
    }
    if (i <= L->length){  //若插入位置不在表尾
        for(k = L->length-1;k >= i-1;k--){
            L->elem[k+1] = L->elem[k];
        }
    }   
    L->elem[i-1] = e;   //将新元素插入
    L->length++;    //长度加1
    return OK;
}

4、顺序表的删除

操作目的:删除L的第i个数据元素,并用e返回其值,L的长度减1

①传入顺序表SqList *L(要加*:因为该操作要改变顺序表),第i个位置,该位置元素值e

②判断顺序表是否为空以及i在不在顺序表范围内

③给e赋上该位置元素值

④如果删除位置不在最后位置,要把该位置后的元素全都向前移位

⑤长度减1

Status ListDelete(SqList *L, int i, ElemType *e){
    int k;
    if(L->length == 0){   //线性表为空
        return ERROR;
    }
    if(i < 1 || i > L->length){ //删除位置不正确
        return ERROR;
    }
    *e = L -> elem[i-1];
    if(i < L->length){  //如果删除位置不在最后位置
        for(k = i;k < L->length;k++){
            L->elem[k-1] = L->elem[k];
        }
    }
    L->length--;    //长度减1
    return OK;
}

5、获取顺序表某位置的元素

操作目的:用e返回L中第i个数据元素的值 

①判断顺序表是否为空,以及i是否在顺序表中

②给e赋上该位置元素值

Status GetElem(SqList L, int i, ElemType *e){
    if(L.length == 0 || i<1 || i>L.length){
        return ERROR;
    }
    *e = L.elem[i-1];
    return OK;
}

6、读取顺序表所有元素

void OutPut(SqList L){
    printf("当前顺序表的长度:%d\n", L.length);
    for(int i = 0; i < L.length; i++){
        printf("%d ",L.elem[i]);
    }
    printf("\n");
}

7、主函数调用

int main()
{
    SqList L;
    printf("------构造一个空的线性表L------\n");
    InitList(&L);
    OutPut(L);  //打印结果
    printf("------测试插入10个数------\n");
    for(int i = 1;i <= 10; i++){
        ListInsert(&L,i,i);
    }
    OutPut(L);  //打印结果
    printf("------在第三位之前插入0------\n");
    ListInsert(&L,3,0);
    OutPut(L);  //打印结果
    printf("------删除第6位的数据------\n");
    ElemType e;
    ListDelete(&L,6,&e);
    printf("删除的数据为:%d\n", e);
    OutPut(L);  //打印结果
    printf("------获取元素操作------\n");
    GetElem(L,5,&e);
    printf("得到第5个元素:%d", e);
}

8、运行结果

9、优缺点

优点:空间利用率高

缺点:插入和删除操作需要移动大量元素

链式存储结构

单链表

1、说明:

首元节点:链表中存储第一个数据元素的节点

头节点:首元节点之前设置的节点

头指针:指向链表中第一个节点的指针

2、增设头节点的作用:

1、便于首元节点的处理

增加头节点之后,首元节点的地址保存在头节点的指针域中,则对链表第一个元素的操作和其他元素操作一样,无需进行特殊处理

2、便于空表和非空表统一处理

增设头节点后,无论链表是非为空,头指针都是指向头节点的非空指针

3、单链表的特点:

1、随机存储:

各个元素的存储位置是随意的

2、顺序存取:

单链表是非随机存取的存储结构,要取得第i个元素必须从头指针出发顺链表进行查找

具体操作: 

1、定义链表

typedef struct node{
	int data;		  //数据域 
	struct node *next;//指针域 
}Lnode,*List;

2、初始化链表

status Init(list &L)
{
	L=new node;
	L->next=NULL;
	return OK;
}

3、创建链表

void creat(List &L,int n)//头插法 
{
	L=new node;
	L->next=NULL;//创建只有一个空节点的新链表 
	for(int i=0;i<n;i++)
	{
		List p=new node;//生成一个新节点 
		cin>>p->data ;//给新节点赋值 
		p->next =L->next ;//将此元素插在头节点之后1 
		L->next =p;//将此元素插在头节点之后2
	}
}
void creat(List &L,int n)//尾插法 
{
	L=new node;
	L->next=NULL;//创建只有一个空节点的新链表
	list t=new node;
	t=L; 
	for(int i=0;i<n;i++)
	{
		List p=new node;//生成一个新节点 
		cin>>p->data ;//给新节点赋值 
		p->next =NULL ; 
		t->next =p;//将此节点插在尾节点之后
		t=p;//位移,使t一直是最后一个节点 
	}
}

4、取值

status get(List L,int i,int &e)//因为要给e赋值,即对e进行修改所有要加取地址符 
{
	List p=new node;
	p=L->next ;//设置p为移动节点,协助查找第i个元素 
	int j=1;//计数 
	while(p&&j<i)//找到第i个位置的节点 
	{
		p=p->next ;//一直向后查找 
		j++;
	}
	if(!p||j<i)//p为空指针或者j<i返回查找失败 
		return ERROR;
	e=p->data ;//把该节点的数据赋给e 
	return OK;
}

5、查找

List find(List L,int e)
{
	List p=new node; 
	p=L;//移动节点p查找数据域为e的节点 
	while(p&&p->data !=e)//查找 
	{
		p=p->next ;
	}
	/*if(!p&&p->data !=e)
		return NULL;这句可以不用加,因为如果不符合条件,跳出循环后p即是NULL */
	return p;
} 

6、插入

status Insert(List &L,int i,int e)
{
	List p=new node;//设置p为移动节点,协助查找第i个元素 
	p=L;
	int j=0;//(为什么上面查找的时候j=1,这里却等于0呢)好好思考一下偶!! 
	while(p&&j<i-1)//找到第i-1个节点 
	{
		p=p->next ;
		j++;
	}
	if(!p||j>i-1)//错误是返回插入失败 
		return ERROR;
	List t=new node;//开辟新结点便于插入 
	t->data =e;//给新结点赋值 
	t->next =p->next ;//指向第i个节点 
	p-next=t;//代替第i个节点的位置 
	return OK;
} 

7、删除

status Delete(List &L,int i)
{
	List p=new node;//开辟新节点 
	p=L;
	int j=0;//计数 
	while(p&&j<i-1)//位移到j=i-1的位置 
	{
		p=p->next ;
		j++;
	}
	if(!p||j>i-1) return ERROR;
	p->next =NULL;//把第i个节点赋值为空 
	return OK;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值