数据结构详解笔记:第二章 线性表

前言

本章主要详解了线性表(逻辑结构)对应的顺序表和链表(存储结构)的实现方式,其中包含增删改查的操作的多种实现方法及代码,最后还介绍了一些特殊链表的引入,以解决现有的存储结构存在的一些问题缺陷。

总览:

在这里插入图片描述

①线性表的定义和基本操作

定义:

​ 线性表是具有相同类型的n(n>=0)个元素的有限序列,其中n为表长,n=0,该表为空表。

线性表的特点:

​ 1.表中元素个数有限
2.表中元素具有逻辑上的顺序性,在序列中各个元素排序有其先后次序
3.表中元素都是数据元素,每个元素都是单个元素。
4.表中元素的数据类型都相同,这意味着每个元素占有相同大小的存储空间。
5.表中元素具有抽象性,即讨论元素间一对一的逻辑关系,而不考虑元素究竟表示的内容。
6.线性表是一种逻辑结构,表示元素之间一对一相邻的关系。

线性表的九种基本操作:

InitList(&L):初始化表。构造一个空的线性表.
DestroyList(&L):销毁操作。销毁线性表,并释放线性表所占用的内存空间
LocateElem(L,e):按值查找操作。在表中查找具有给定关键字值得元素。
GetELem(L,i):按位查找操作。获取表中第个位置的元素的值。
ListInsert(&L,e):插入操作,在表中的第个位置上插入指定元素e。
ListDelete(&L,&e):删除操作。删除表L中第个位置的元素,并用e返回删除元素的值。
Printlist(u):输出操作。按前后顺序输出线性表的所有元素值。
Empty(L):判空操作。若为空表,则返回TRUE否则返回 FALSE。
Length(u):求表长。返回线性表L的长度,即中数据元素的个数。

②线性表的顺序表示

顺序表的定义:

线性表的顺序存储,又称顺序表。

数组静态分配:
#define Maxsize=50
typedef struct{
    Elemtype data[Maxsize];
    int length;
}sqlist;
数组动态分配:
typedef struct{
    Elemtype *data;
    int length;
}sqlist;

data =new Elemtype[Initsize];//动态获取分配空间;
顺序表的基本操作的实现:
插入操作:
bool InsertList(sqlist &L,int i,Elemtype e){
//i对应的是顺序表的表号,而不是数组的下标。
 if(i<1||i>L.length+1)
 	return false;//插入位置是否合法
 if(L.length>Maxsize)
	return false;//是否有足够的插入空间
 for(int j=L.length;j>=i;j--){
	L.data[j]=L.data[j-1];
 }
    L.data[j]=e;
    L.length++;
    return true;
}
删除操作:
bool ListDelete(sqlist &L,int i,Elemtype &e){
    if(i<1||i>L.length)
        return false;
    e=L.data[i-1];
    for(int j=i;j<=L.length;j++){
        L.data[j-1]=L.data[j];
    }//采用覆盖的方式进行删除
    L.length--;
    return true;
}
按值查找:
int LocateElemtype(sqlist L,Elemtype e){
    for(int j=0;j<L.length;j++){
        if(L.data[j]==e)
            return j+1;
    }
        return 0;
}
顺序表的合并操作:
void Array_imerse(int* L1,int* L2,int* L){
    int k=0,i=0,j=0;
    for(;i<len(L1)&&j<len(L2);){
        if(L1[i]<L2[j])
            L[k++]=L1[i++];
        else
            L[k++]=L2[j++];
    }
    while(i<len(L1)){
        L[k++]=L1[i++];
    }
    while(j<len(L2)){
        L[k++]=L2[j++];
    }
}

③线性表的链式表示

单链表的定义:

线性表的链式存储,又称单链表。

单链表的结构:
typedef struct{
    Elemtype data;
    struct Lnode *next;
}Lnode,*linklist;

注意:Lnode*等价于linklist;

引入头结点的单链表:

在这里插入图片描述

优点:

​ 1.链表的第一个位置和其他位置的操作统一。(插入操作)

​ 2.空表和非空表的操作统一。

单链表的基本操作的实现:
头插法建立单链表:

在这里插入图片描述

linklist linklist_HeadInsert(linklist &L){
    Lnode* s;int x;//s->data=x;
    //初始化头结点
    L=(linklist)malloc(sizeof(londe));
    L->next=NULL;
    scanf("%d",&x);
    while(x!=9999){
        s=(Lnode*)malloc(sizeof(londe));
        s->next=L->next;
        L->next=s;
        scanf("%d",&x);
    }
    return L;
}
尾插法建立单链表:

在这里插入图片描述

linklist linklist_TailInsert(linklist& L){
    Lnode* s,*r=L;int x;
    L=(linklist)malloc(sizeof(Lnode));
    scanf("%d",&x);
    while(x!=9999){
        s=(Lnode*)malloc(sizeof(Lnode));
        s->data=x;
        r->next=s;
        r=s;
        scanf("%d",&x);
    }
    r->next=NULL;
    return linklist;
}
按序号查找&按值查找:

在这里插入图片描述

//按序号查找
Lnode* GetElem(linklist L,int i){
    Londe *p=L->next;
    int j=1;
    if(i==0)//如果是i=0,返回头结点
        return L;
    if(i<0)//如果i<0,返回NULL
        return NULL;
    while(p&&j<i){//p不为空且j<i;
        p=p->next;
        j++;
    }
    return p;
}
//按值查找
int ElemLocate(linklist L,int x){
    Londe* p=L->next;int j=1;
    while(p&&p->data!=x){
        p=p->next;
        j++;
    }
    return j;
}
插入节点操作:

在这里插入图片描述

bool linklist_BackInsert(linklist &L,int i,int e){
	Lnode* p=GetElem(L,i-1);
    if(p==NULL)
        return false;
	Lnode* q=(Londe*)malloc(sizeof(lnode));
    q->data=e;
    q->next=p->next;
    p->next=q;
}
删除节点操作:

在这里插入图片描述

void linklist_LnodeDelete(Lnode* p){
    Lnode* q=p->next;
    p->next=q->next;
    free(q);
}
单链表的逆置操作:

在这里插入图片描述

linklist* linklist_LondeInverse(linklist &L){
    Lnode* p=L;//拿到单链表头部的指针
    while(p->next){
        p=p->next;
    }
    Lnode* r=p;//拿到单链表尾部的指针
    
    Lnode* q;//q作为p->next的节点指针
    p=L;//p作为头结点指针,指向head节点
    
    while(p->next!=r){
        q=p->next;//拿到第一个节点node(L->next节点)
        
        p->next=q->next;//将该节点插入到r节点的后面,使用插入操作
        q->next= r->next;
        r->next=q;
    }
    return p;
}
单链表的合并操作:
//合并后,数据从大到小依次排列
linklist* linklist_immerse(linklist &L1,linklist &L2){
    Lnode* r=L1;
    Lnode *p=L1->next,*q=L2->next;
    while(p&&q){
        if(p->data<q->data){
            p->next=r->next;
            r->next=p->next;
            p=p->next;
        }
        else{
            q->next=r->next;
            r->next=q->next;
            q=q->next;
        }
    }//使用头插法合并链表
    while(p){
            p->next=r->next;
            r->next=p->next;
            p=p->next;
        }
    while(q){
            q->next=r->next;
            r->next=q->next;
            q=q->next;
        }
    free(p);free(q);
    return r;
}
//合并后,数据从小到大依次排列
linklist* linklist_immerse(linklist &L1,linklist &L2){
    Lnode* r=L1;
    Lnode *p=L1->next,*q=L2->next;
    while(p&&q){
        if(p->data<q->data){
           r->next=p;
           p=p->next;
           r=r->next;
        }
        else{
  		   r->next=q;
           q=q->next;
           r=r->next;
        }
    }//使用尾插法合并链表
    if(p){
        r->next=p;
    }
    if(q){
        r->next=q;
    }
    free(p);free(q);
    return L1;
}

④特殊链表

双链表
双链表的结构:

在这里插入图片描述

typedef struct{
  Elemtype data;
  struct Dnode *prior,*next;   
}Dnode,*Dlinklist;
双链表的插入操作:

在这里插入图片描述

注意:

​ 双链表的表尾位置的插入操作和表头位置的插入操作是不一样的,因为表尾为空NULL并且没有prior指针。

双链表的删除操作:

在这里插入图片描述

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super__Tiger

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值