【C语言督学训练营 第十天】三篇文章吃透数据结构中的线性表(一)----- 顺序表(数组)的增删改查与销毁

前言

将会分为三篇博客,由浅入深的介绍数据结构中的线性表,线性表是数据结构中最常用的数据结构也是最基础的数据结构,在以后学习到的栈与队列的实现、二叉树、图等都会用到线性表结构。将会分为三篇博客详细介绍线性表,本篇博客主要说一下顺序表的原理、顺序表的初始化、插入、删除、查找,并讲解一下链表的实现原理。

在正式介绍线性表之前可以先看看有关线性表的考研真题!
2010 年(顺序表)
42.(13 分)设将 n(n > 1)个整数存放到一维数组 R 中。试设计一个在时间和空间两方面都尽可能高效的算法。将 R 中保存的序列循环左移 p(0 < p < n)个位置,即将 R中的数据由(X0, X1, , Xn1)变换为(Xp, Xp+1,, Xn1, X0, X1, , Xp1)。要求:

  • 1)给出算法的基本设计思想。
  • 2)根据设计思想,采用 C、C++或 Java 语言描述算法,关键之处给出注释。
  • 3)说明你所设计算法的时间复杂度和空间复杂度。

2012 年(链表)
42.假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,则可共享相同的后缀存储空间,例如,“loading”和“being”的存储映像如下图所示。
在这里插入图片描述

设 str1 和 str2 分别指向两个单词所在单链表的头结点,链表结点结构为在这里插入图片描述
请设计一个时间上尽可能高效的算法,找出由 str1 和 str2 所指向两个链表共同后缀的起始位置(如图中字符 i 所在结点的位置 p)。要求:

  • 1)给出算法的基本设计思想。
  • 2)根据设计思想,采用 C 或 C++或 Java 语言描述算法,关键之处给出注释。
  • 3)说明你所设计算法的时间复杂度。

顺序表结合排序出了很多大题,链表本身出了很多大题,都非常重要!

一、线性表概念

线性表定义
在这里插入图片描述
线性表特点
在这里插入图片描述
上面两个图说的均是线性表的逻辑结构,与存储结构没有关系,具体关系如下所示。
线性表分类

  • 线性表的顺序表示
    • 又名顺序表
    • 在逻辑结构上是顺序存储
    • 在存储结构上是顺序存储
  • 线性表的链式表示
    • 又名链表
    • 在逻辑结构上是 顺序存储
    • 在存储结构上是 随机存储

二、顺序表(线性表的顺序表示)

1.基本介绍

在这里插入图片描述
顺序表的定义:

#define MaxSize 50 //定义线性表的长度
typedef struct {
    
    
	ElemType data[Maxsize] ;	//顺序表的元素
	int len;					//顺序表的当前长度
} sqList;	//顺序表的类型定义

ElemType指任意类型

2.增删改查原理与实战

先看一看效果。
在这里插入图片描述

在顺序表中增加一个元素
在这里插入图片描述
在这里插入图片描述
经过不懈的努力,终于编码完毕下面为插入元素的代码:

bool insertData(myList* mylist,int i,ElemType e){
    
    
    //三个参数分别是结构体数组、元素要插入的位置、要插入的元素

    //判断数组长度
    if(mylist==NULL||i<=0||mylist->length+1<i||i>MaxSize){
    
    
        return false;
    }
    int j;
    for(j=mylist->length;j>=i;j--){
    
    
        mylist->data[j]=mylist->data[j-1];
    }
    mylist->data[i-1]=e;
    mylist->length+=1;
    return true;
}

在顺序表中删除一个元素
在这里插入图片描述
在这里插入图片描述
删除元素有两种方式,一种是按照序号(也就是位置)删除,一种是按照元素进行删除,这里两种方法我都实现了一下;
上面循环内的公式:l.data[j-1]=l.data[j]方式往前移动数据,可以有效地防止数组越界等问题。如果不是这个公式那么需要改变循环条件。
按照序号进行删除

//删除元素(删除指定位置)
bool deleteDataByI(myList* mylist,int i){
    
    
    if(mylist==NULL||i<=0||mylist->length<i||i>MaxSize){
    
    
        return false;
    }
    int j=i;
    for (;j<mylist->length;j++){
    
    
        mylist->data[j-1]=mylist->data[j];
    }
    // 删除完毕之后,将多出来的一个空位赋上\0
    mylist->data[mylist->length-1]=baseElem;
    mylist->length-=1;

}

按照元素进行删除

//删除元素(遍历删除指定元素)
bool deleteDataByE(myList* mylist,ElemType e){
    
    
    // 删除指定元素(搜索,删除)
    if(mylist==NULL){
    
    
        return false;
    }
    int j=0;
    // 临时记下原来长度
    int tempIndex=mylist->length;
    // 第一遍遍历(去除相关元素)
    for(;j<tempIndex;j++){
    
    
        if(mylist->data[j]==e){
    
    
            mylist->data[j]=baseElem;
            mylist->length-=1;
        }
    }
    // 将数组内的空缺由后面元素填补掉
    int i=0;
    for(;i<mylist->length;i++){
    
    
        if(mylist->data[i]==baseElem){
    
    
            for(j=i+1;j<tempIndex;j++){
    
    
                if(mylist->data[j]!=baseElem){
    
    
                    mylist->data[i]=mylist->data[j];
                    mylist->data[j]=baseElem;
                    break;
                }
            }
        }
    }

}

查询元素与打印元素

//查询元素
int searchElement(myList* mylist,ElemType e){
    
    
    int i=0;
    for(;i<mylist->length;i++){
    
    
        if(mylist->data[i]==e){
    
    
            return true;
        }
    }
    return false;
}
//打印元素
void printData(myList* mylist){
    
    
    if(mylist==NULL){
    
    
        printf("null");
    }
    int i=0;
    for(;i<mylist->length;i++){
    
    
        printf("%3c",mylist->data[i]);
    }
    printf("\n");
}

清理顺序表

 memset(p->data,baseElem, MaxSize);
 p->length=0;

使用动态内存创建数组
在这里插入图片描述

总结与源码

顺序表就是我们C语言中常说的数组,无论从逻辑结构,存储结构来说都是顺序存储。有优点也有缺点,总结如下:
在这里插入图片描述

源码
代码思路:这里由于用的是纯c语言写的,所以自定义了bool类型,在插入数据时需要注意临界条件,不能超出数组,也不能超出现有长度+2,也就是不能随机插入在空白区域,插入之后数据之间要连贯,删除函数的话按索引删除与插入相类似,按元素删除是先删除相关元素,然后用两个索引将元素聚拢到一块,查询与打印函数比较简单就不说了!

//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxSize 50
#define baseElem '\0'
# define bool int
# define true 1
# define false 0
typedef char ElemType;
//数组类型
typedef struct{
    
    
    ElemType data[MaxSize];
    int length;
}myList;
//插入元素
bool insertData(myList* mylist,int i,ElemType e){
    
    
    //三个参数分别是结构体数组、元素要插入的位置、要插入的元素

    //判断数组长度
    if(mylist==NULL||i<=0||mylist->length+1<i||i>MaxSize){
    
    
        return false;
    }
    int j;
    for(j=mylist->length;j>=i;j--){
    
    
        mylist->data[j]=mylist->data[j-1];
    }
    mylist->data[i-1]=e;
    mylist->length+=1;
    return true;
}
//删除元素(删除指定位置)
bool deleteDataByI(myList* mylist,int i){
    
    
    if(mylist==NULL||i<=0||mylist->length<i||i>MaxSize){
    
    
        return false;
    }
    int j=i;
    for (;j<mylist->length;j++){
    
    
        mylist->data[j-1]=mylist->data[j];
    }
    // 删除完毕之后,将多出来的一个空位赋上\0
    mylist->data[mylist->length-1]=baseElem;
    mylist->length-=1;

}
//删除元素(遍历删除指定元素)
bool deleteDataByE(myList* mylist,ElemType e){
    
    
    // 删除指定元素(搜索,删除)
    if(mylist==NULL){
    
    
        return false;
    }
    int j=0;
    // 临时记下原来长度
    int tempIndex=mylist->length;
    // 第一遍遍历(去除相关元素)
    for(;j<tempIndex;j++){
    
    
        if(mylist->data[j]==e){
    
    
            mylist->data[j]=baseElem;
            mylist->length-=1;
        }
    }
    // 将数组内的空缺由后面元素填补掉
    int i=0;
    for(;i<mylist->length;i++){
    
    
        if(mylist->data[i]==baseElem){
    
    
            for(j=i+1;j<tempIndex;j++){
    
    
                if(mylist->data[j]!=baseElem){
    
    
                    mylist->data[i]=mylist->data[j];
                    mylist->data[j]=baseElem;
                    break;
                }
            }
        }
    }

}
//查询元素
int searchElement(myList* mylist,ElemType e){
    
    
    int i=0;
    for(;i<mylist->length;i++){
    
    
        if(mylist->data[i]==e){
    
    
            return true;
        }
    }
    return false;
}
//打印元素
void printData(myList* mylist){
    
    
    if(mylist==NULL){
    
    
        printf("null");
    }
    int i=0;
    for(;i<mylist->length;i++){
    
    
        printf("%3c",mylist->data[i]);
    }
    printf("\n");
}
int main() {
    
    
    myList *p=(myList*)malloc(sizeof (myList));
    // 初始化
    memset(p->data,baseElem, MaxSize);
    p->length=6;
    p->data[0]='h';
    p->data[1]='o';
    p->data[2]='w';
    p->data[3]='a';
    p->data[4]='r';
    p->data[5]='e';
    printf("before insert : ");
    printData(p);
    insertData(p,3,'v');
    insertData(p,6,'v');
    insertData(p,8,'v');
    printf("after  insert : ");
    printData(p);
    printf("delete by index : ");
    deleteDataByI(p,4);
    printData(p);
    printf("delete by element : ");
    deleteDataByE(p,'v');
    printData(p);
    printf("search: %d\n", searchElement(p,'a'));
    printf("search: %d", searchElement(p,'c'));
    return 0;
}

在下一小节我们将会介绍C语言链表的增删改查与销毁,如有兴趣请多多关注!

猜你喜欢

转载自blog.csdn.net/apple_51931783/article/details/129050443
今日推荐