11、12.C++考研线性表基础操作

本文详细介绍了顺序表的静态和动态分配,单链表的定义、初始化、查找、插入和删除操作,以及双链表和循环链表的构建与操作。涵盖了链表结构的基础知识和关键函数实现。
摘要由CSDN通过智能技术生成

目录

一、顺序表

(1)静态分配

(2)动态分配

(3)基本操作

1)初始化

2)动态扩展空间

3)插入

3)删除

二.单链表(带头结点)

1.定义结构体

2.初始化

3.判空and求表长

4.查找元素

(1)按位序

(2)按值

5.插入元素

        (1)指定结点的后插操作

        (2)指定结点的前插操作

6.删除

        (1)按指定结点

        (2)替换技巧

7.单链表的建立

(1)尾插法

(2)头插法

三、双链表

1.初始化

2.插入(后插)

3.删除(后删)

4.遍历

(1)前向遍历

(2)后向遍历

(4)查找

1)按值查找

2)按位查找

四、循环链表

1.循环单链表

(1)操作

        1)初始化

        2)判空

        3)判头

        4)判尾

        5)插入删除

2.循环双链表

(1)操作

        1)初始化

        2)判空

        3)判头

        4)判尾

        5)插入删除


一、顺序表

(1)静态分配

#define MaxSize 50 
typedef int ElemType;

typedef struct{
    ElemType data[MaxSize];
    int length;
}SqList;

(2)动态分配

#define InitSize 100  //初始定义的长度
typedef int ElemType;

typedef struct {
     ElemType *data; //指向连续空间的第一个ele
     int MaxSize,length; //最大长度和当时长度
 }SeqList;

(3)基本操作

1)初始化

//静态分配初始化
void InitList(SqList &L){
    L.length = 0;
}

 直接令length=0,不可省略

此处可以初始化值,else会被内存中曾经使用过此处内存的脏data影响,but此步骤可以省略

reason:遍历时是i到length-1,so初始化length即可,不会读取到后面的脏data

//动态分配初始化
void InitList(SeqList &L){
    L.lenth = 0;
    L.MaxSize = InitSize;
    L.data = (ElemType*)malloc(MaxSize * sizeof (SeqList));
}

初始化表长度和最大长度,指针开辟新空间,指向第一个位置

2)动态扩展空间

当顺序表满了之后,定义一个新的指针指向原顺序表,原顺序表的data指针在内存中申请新的一段大的连续的空间,再将原来顺序表拷贝到新的顺序表中,释放新指针

void IncreaseSize(SeqList &L,int len){ //len表示增加的长度
    ElemType *L2 = L.data;//SeqList的第一个ele地址
    L.data = (ElemType *) malloc(sizeof(ElemType)*(MaxSize+len));
    for (int i = 0; i < MaxSize; ++i) {
        L.data[i]=L2[i];
    }
    L.MaxSize = L.MaxSize + len;
    free(L2);
}

attn:①静态arr和动态arr都有MaxSize,含义不同,静态arr中是常量,不可更改;动态arr中是SeqList的属性,可以更改

        ②一开始MaxSize是初始化定义的InitSize,表示最初定义的顺序表最大长度

        ③i<MaxSize  《==》i<L.length  ∵此时 MaxSize == L.length

        ④SeqList的MaxSize需要+len

3)插入

在L的第i个位置插入元素e

bool提示是否插入成功

bool ListInsert(SqList &L,int i,ElemType e){//i为位序
    if(i<1 || i>L.length+1){//超出范围,ele得挨着
        return false;
    }
    if(L.length +1 >MaxSize){//表满了
        return false;
    }
    int j;
    for (j = L.length; j >= i ; j--) { 
        L.data[j-1] = L.data[j];
    }
    L.data[i-1] = e; 
    L.length++;//attn
    return true;

3)删除

删除L中第i个位置的ele,用e保存

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;
}

二.单链表(带头结点)

初始不考察不带头结点的单链表,so此处仅展示带头结点的单链表

1.定义结构体

typedef int ElemType;

typedef struct LNode {
    ElemType data; //数据域
    struct LNode *next;//指针域
} LNode, *LinkList;

2.初始化

bool InitList(LinkList &L){
    L = (LNode *) malloc(sizeof(LNode));//申请空间
    L = NULL;//空链表
    return true;
}

3.判空and求表长

bool isEmpth(LinkList L){
    return L->next;
}

int Length(LinkList L) {
    LinkList p = L;
    int len = 0;
    while (NULL != p->next) {
        p = p->next;
        len++;
    }
    return len;
}

4.查找元素

(1)按位序

LNode *GetElem(LinkList L, int i) {
    LNode *p;
    p = L;
    int j = 0;
    while (NULL != p && j < i) {
        p = p->next;
        j++;
    }
    return p;
}

(2)按值

当p指向元素的值==e,停止

LNode* LocationElem(LinkList L,ElemType e){
    LNode *p =L;
    while(NULL != p->next && p->data != e){
        p=p->next;
    }
    return p;
}

5.插入元素

        (1)指定结点的后插操作

在L的第i个位置插入e

之后找到第i-1个元素的位置,在该ele后插入

bool ListInsert(LinkList &L, int i, ElemType e) {
    if (i < 1) return false;//i范围不合法
    LNode *p;
    LNode *s = (LNode *) malloc(sizeof(LNode));
    p = L;
    int j = 0;
    while(NULL != p && j<i-1 ){
        p=p->next;
        j++;
    }
    if(NULL == p) return false;//超出范围了
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}

 结合之前学习的:查找第i-1个元素

//观察
//按位序
LNode *GetElem(LinkList L, int i) {
    LNode *p;
    p = L;
    int j = 0;
    while (NULL != p && j < i) {
        p = p->next;
        j++;
    }
    return p;
}

汇总

//so
bool ListInsert(LinkList &L, int i, ElemType e) {
    if (i < 1) return false;//i范围不合法
    LNode *p;
    LNode *s = (LNode *) malloc(sizeof(LNode));
    p = GetElem(LinkList L, int i-1);
    if(NULL == p) return false;//超出范围了
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}

        (2)指定结点的前插操作

step1:判断i是否合法

step2:找到第i个ele

step3:先将第i个ele 的data保存到新结点中,再将第i个ele 的data赋予e,再进行链接

bool ListPerInsert(LinkList L, int i, ElemType e) {
    LNode *p = L;
    if (i < 1) return false;
    int j = 0;
    while (p != NULL && j < i) {
        p = p->next;
        j++;
    }
    LNode *s = (LNode *) malloc(sizeof(LNode));
    if(s == NULL) return false; //内存分配失败
    s->next = p->next;
    s->data = p->data;
    p->data = e;
    p->next = s;
    return true;
}

6.删除

        (1)按指定结点

bool ListDelete(LinkList &L,int i,ElemType &e){
    if(i<1) return false;
    LNode *p;
    p = L;
    int j = 0;
    while (NULL != p && j < i-1) {
        p = p->next;
        j++;
    }
    if(NULL == p || p->next == NULL) return false;
    LNode *q = p->next;
    e = q->data;
    p->next = q->next;
    free(q);
    return true;
}

        (2)替换技巧

bool ListDeleteRePlace(LinkList &L, int i, ElemType e) {
    if (i < 1) return false;
    LNode *p = L;
    int j = 0;
    while (NULL != p && j < i) {
        p = p->next;
    }
    if (p == NULL) return false;
    LNode *s = p->next;
    p->data = s->data;
    p->next = s->next;
    free(s);
    return true;
}

7.单链表的建立

(1)尾插法

用一个指针指向尾结点,执行后插操作

LinkList ListTailInsert(LinkList &L) {
    L = (LNode*) malloc(sizeof(LNode));
    L->next=NULL;
    LNode *p = L;
    ElemType e;
    e = scanf("%d", &e);
    while (e != 9999) {
        LNode *s = (LNode *) malloc(sizeof(LNode));
        s->data = e;
        s->next = p->next;
        p->next = s;
        p = p->next;
        scanf("%d", &e);
    }
    return L;
}

(2)头插法

用一个指针指向头结点,执行后插操作

LinkList ListHeadInsert(LinkList &L){
    L = (LNode*) malloc(sizeof(LNode));
    L->next=NULL;
    ElemType e;
    e = scanf("%d", &e);
    LNode  *s;
    while (e != 9999) {
        s = (LNode *) malloc(sizeof(LNode));
        s->data = e;
        s->next = L->next;
        L->next = s;
        scanf("%d", &e);
    }
    return L;
}

三、双链表

1.初始化

bool InitLinkList(DLinkList &L) {
    L = (DNode *) malloc(sizeof(DNode));
    L->next = NULL;
    L->prior = NULL;
    return true;
}

2.插入(后插)

在第i个位置插入元素e

查找第i个位置+后插

bool DLinkListInsert(DLinkList &L, int i, ElemType e) {
    if (i < 1) return false;
    DNode *p = L, *q, *s;
    s = (DNode *) malloc(sizeof(DNode));
    s->data = e;
    int j = 0;
    while (NULL != p && j < i - 1) {
        p = p->next;
    }
    if (p == NULL) return false;
    q = p->next;
    s->next = q;
    s->prior = p;
    q->prior = s;
    p->next = s;
    return true;
}

3.删除(后删)

删除p结点的后继结点
bool DeleteNextNode(DNode *p){
    if (p == NULL) return false;
    DNode *q=p->next;
    q = p->next;
    if(q->next!=NULL)//q不是最后一个结点
        q->next->prior = p;
    p->next = q->next;
    free(q);
    return true;
}

4.遍历

(1)前向遍历

    while(p!=NULL){
        p = p->prior;
    }

//跳过头结点
    while(p->prior!=NULL){
        p = p->prior;
    }

(2)后向遍历

    while (p != NULL) {
        p->next = p;
    }

(4)查找

1)按值查找
2)按位查找

四、循环链表

1.循环单链表

(1)操作

        1)初始化
bool ListInit(LinkList &L) {
    L = (LNode *) malloc(sizeof(LNode));
    if(L==NULL) return false;//内存不足
    L->next = L;
    return true;
}
        2)判空
bool isEmpty(LinkList L){
    return (L->next == L);
}
        3)判头
bool isHead(LNode* p){
    return p == L->next;
}
        4)判尾
bool isTail(LNode* p){
    return NULL == p->next;
}
        5)插入删除

2.循环双链表

(1)操作

        1)初始化
bool DLinkListInit(DLinkList &L){
    L = (LNode *) malloc(sizeof(DNode));
    if(L==NULL) return false;//内存不足
    L->next = L;
    L->prior =L;
    return true;
}
        2)判空
bool isEmpty(DLinkList L){
    return L->next == L;
}
        3)判头
bool isHead(DNode* p){
    return p->prior == L;
}
        4)判尾
bool isTail(DNode* p){
    return p->next == L;
}
        5)插入删除
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

blue_blooded

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

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

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

打赏作者

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

抵扣说明:

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

余额充值