C语音《数据结构》中顺序表学习

学习完数据结构到现在已经好几年,也忘了差不多了,最近重新复习起来,发现自己很多东西都忘掉了。所以现在整理这个学习笔记,加上自己的一些理解,由浅入深,也希望能给有需要的初学者们了解一下。

最简单的数据结构

在学习了数据类型,我们知道了“int i”表示“i”这个变量意思是“i”为整型的一种数据类型。进而学习了数组,我们知道了“int a[3]”表示这是都是存放整型的,长度为3的一种数据类型。

#include<stdio.h>

int main(){
    int a[3]={1,2,3};
    for(int i=0;i<3;i++){
        printf("第%d个数据为:%d\n",i+1,a[i]);
    }
    return 0;
}

运行效果:

我以下图为例,浅红色格子代表内存中存储的数据:

由此,我们可以由以上的数组建立一个简单的数据结构SeqList:

#include<stdio.h>
// 固定写法,定义一个名为SeqList的结构体
typedef struct SeqList {
    int data[3];
    int length;
}Array; // 给结构体命名为Array

int main(){
    // 定义array变量
    Array array;
    // 分别给结构体中的数据赋值
    array.data[0]=1;
    array.data[1]=2;
    array.data[2]=3;
    array.length=3;
    printf("结构体的长度为:%d\n",array.length);
    for(int i=0;i<array.length;i++){
        printf("第%d个数据为:%d\n",i+1,array.data[i]);
    }
    return 0;
}

运行效果:

我们会发现,上面的结构体输出的内容和原本使用数组的效果相差无几,区别在于仅多了一个“length”(长度)。但多了这个长度,我们就可以在遍历时,不必写死循环的次数,增加了灵活性了。

顺序表的方法

我们在上面的例子中对结构体数据赋值的方式,比用数组麻烦多了,所以接下来我们要定义一些方法,才能体现得出数据结构的魅力。

初始化、插入、遍历的方法

#include<stdio.h>
//固定写法,定义一个名为SeqList的结构体
typedef struct SeqList {
    //定义一个长度为5的数据空间
    int data[5];
    int length;
}Array; //给结构体命名为Array

//初始化顺序表
void SeqListInit(Array* array){
    array->length=0;
}

//顺序表插入的方法(末尾插入)
void SeqListInsert(Array* array,int data){
    array->data[array->length] = data;
    array->length++;
}

//打印顺序表
void SeqListPrintf(Array array){
    printf("结构体的长度为:%d\n",array.length);
    for(int i=0;i<array.length;i++){
        printf("第%d个数据为:%d\n",i+1,array.data[i]);
    }
}

int main(){
    //定义array变量
    Array array;
    //初始化顺序表(采用指针传递结构体)
    SeqListInit(&array);
    
    //分别给结构体中的数据赋值
    SeqListInsert(&array,1);
    SeqListInsert(&array,2);
    SeqListInsert(&array,3);
    
    //打印顺序表
    SeqListPrintf(array);
    return 0;
}

运行效果还是一样的,就不额外截图了。

我们对比数组的赋值、遍历可以发现,在我们的这个结构体的赋值中,通过调用插入方法,我们已经不再需要将数据指定插入到数组的第几个位置,大大地提升了我们对于数据插入的灵活性。同时,我们初始创建结构体时,已经一次性开辟好了一个空间为5的数组空间,而不需要逐个赋值时逐个开辟空间,提升了程序效率

规范顺序表结构及方法

在以上的代码中,我们的顺序表已经有了雏形,但其中还是有很多风险的,例如我们只开辟了一个长度为5的数组空间,如果插入的数据多了,是不是又要去修改代码呢?如果我们一下子开辟的空间多了,很明显又过于浪费,因此我们需要做到动态开辟空间。同时,在插入时,假如插入的数据量超过了我们开辟的内存空间,程序也必定出错。

因此,我对顺序表的其他方法进行了补充:

#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
#define DefaultSize 10
#define TRUE 1
#define FALSE 0
#define ERROR 0
typedef int DataType;

//固定写法,定义一个名为SeqList的结构体
typedef struct SeqList {
    DataType* data;
    int length;
    int maxLength;
}SeqList;

//动态开辟内存空间
int SeqListAddSize(SeqList* seqList){
    if(seqList->length+DefaultSize > MaxSize){
        printf("已超出最大分配空间\n");
        return ERROR;
    }
    seqList->data = (DataType*)realloc(seqList->data,(seqList->length+DefaultSize)*sizeof(DataType));
    seqList->maxLength+=DefaultSize;
    return TRUE;
}

//初始化顺序表
void SeqListInit(SeqList* seqList){
    seqList->data = (DataType*)malloc(DefaultSize*sizeof(DataType));
    seqList->length=0;
    seqList->maxLength=DefaultSize;
}
//判断顺序表是否为空
int SeqListWhetherEmpty(SeqList seqList){
    return seqList.length == 0 ? TRUE : FALSE;
}

// 指定位置插入
int SeqListInsertByIndex(SeqList* seqList,DataType data,int index){
    if(index<1 || index>seqList->length+1){
        printf("插入位置不正确\n");
        return ERROR;
    }
    // 检查空间大小
    if(seqList->length >= seqList->maxLength){
        if(!SeqListAddSize(seqList)){
            printf("插入数据失败!\n");
            return ERROR;
        }
    }
    // 插入到中间位置时,将后几项都向后移动一位,最后将数据插入到指定的位置
    for(int i=0;i<seqList->length-index+1;i++){
        seqList->data[seqList->length-i]=seqList->data[seqList->length-i-1];
    }
    seqList->data[index-1]=data;
    seqList->length++;
    return TRUE;
}
//头插入
void SeqListFirstInsert(SeqList* seqList,DataType data){
    SeqListInsertByIndex(seqList,data,1);
}
//末尾插入
void SeqListInsert(SeqList* seqList,DataType data){
    SeqListInsertByIndex(seqList,data,seqList->length+1);
}

// 删除指定位置元素
int SeqListRemoveByIndex(SeqList* seqList,int index){
    if(index<1 || index>seqList->length){
        printf("删除位置不正确\n");
        return ERROR;
    }
    // 删除时,将后几项都向前移动一位
    for(int i=index-1;i<seqList->length-1;i++){
        seqList->data[i]=seqList->data[i+1];
    }
    seqList->length--;
    return TRUE;
}
// 删除第一个元素
void SeqListRemoveFirst(SeqList* seqList){
    SeqListRemoveByIndex(seqList,1);
}
// 删除最后一个元素
void SeqListRemoveLast(SeqList* seqList){
    SeqListRemoveByIndex(seqList,seqList->length);
}

// 获取指定位置元素
DataType SeqListGetElementByIndex(SeqList* seqList,int index){
    if(SeqListWhetherEmpty(*seqList)){
        printf("顺序表为空");
        return NULL;
    }
    if(index<1 || index>seqList->length){
        printf("查找位置不正确\n");
        return NULL;
    }
    return seqList->data[index-1];
}
// 获取第一个元素
DataType SeqListGetFirstElement(SeqList* seqList){
    return SeqListGetElementByIndex(seqList,1);
}
// 获取最后一个元素
DataType SeqListGetLastElement(SeqList* seqList){
    return SeqListGetElementByIndex(seqList,seqList->length);
}

// 销毁顺序表
void SeqListDestroy(SeqList* seqList){
    free(seqList->data);
    seqList->data=NULL;
    seqList->length=0;
    seqList->maxLength=0;
    printf("顺序表已销毁");
}
//打印顺序表
void SeqListPrintf(SeqList seqList){
    printf("遍历顺序表-----长度为:%d\n",seqList.length);
    for(int i=0;i<seqList.length;i++){
        printf("第%d个数据为:%d\n",i+1,seqList.data[i]);
    }
}

int main(){
    //定义array变量
    SeqList array;
    //初始化顺序表(采用指针传递结构体)
    SeqListInit(&array);

    //分别给结构体中的数据赋值
    SeqListInsert(&array,1);
    SeqListFirstInsert(&array,2);
    SeqListInsert(&array,3);
    SeqListInsertByIndex(&array,4,2);
    SeqListInsertByIndex(&array,5,3);
    SeqListInsertByIndex(&array,6,1);
    //打印顺序表
    SeqListPrintf(array);
    printf("第一个元素是%d\n",SeqListGetFirstElement(&array));
    printf("最后一个元素是%d\n",SeqListGetLastElement(&array));

    SeqListRemoveByIndex(&array,4);
    SeqListRemoveFirst(&array);
    SeqListRemoveLast(&array);
    //打印顺序表
    SeqListPrintf(array);
    SeqListDestroy(&array);
    return 0;
}

运行效果如图:

此处卖个关子,按照代码来执行,最终的数据排序是怎么样的呢?欢迎在评论区留言!

学习参考链接:

https://www.cnblogs.com/Sock/p/Sequence_table.html

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值