1. 顺序表(sqlist)

顺序表:是数据结构里的线性结构,数据之间呈现线性关系,且在内存上,连续存储(顺序存储)。顺序表是线性表的一种,另外线性表还包括链表。

2. 顺序表的创建

完成顺序表的一系列操作,首先要创建3个文件:sqlist.h 、sqlist.c 、main.c 。

(1)在头文件 sqlist.h 中,作以下定义:

#ifndef _sqlist_h_
#define _sqlist_h_
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

typedef  int data_t;//重命名一个int的数据类型data_t, 专门用来修饰顺序表中的data数据

#define SIZE 10 //宏定义数组大小,可修改

//顺序表结构体
typedef struct{
    data_t data[SIZE];
    int last;//表尾指针
}sqlist;

//创建顺序表
sqlist *sqlist_create();

以上包含了一些基本头文件,对相关数据的准备(宏定义、重命名数据类型),定义了顺序表的结构体,以及创建顺序表的函数定义。

(2)在 sqlist.c 文件中封装创建顺序表的功能 

#include "sqlist.h"

//创建数据表
sqlist *sqlist_create()
{
    //给顺序表结构体手动分配空间
    sqlist *head = (sqlist *)malloc(sizeof(sqlist));

    //验证是否成功申请到了空间
    if (NULL == head){
        printf("malloc failed!\n");
        return NULL;
    }
    memset(head, 0, sizeof(sqlist));//给申请到的空间填充0(视情况可省略)

    head->last= -1;//初始化尾指针

    return head;//将申请到的空间首地址返回
}

(3)在主函数中调用封装的创建函数

int main(int argc, char *argv[])
{ 
    //创建链表
    node *head = linklist_create ();//结构体指针接收数据
    
    //判断是否创建成功
    if (head == NULL)
    {
        printf("malloc failed!\n");
        return -1;
    }
    return 0;
}

3. 顺序表的基础附属操作

要操作顺序表,少不了一系列的附属功能(判空、判满、清空、求长度、显示、回收),实现这些功能让你的顺序表更健壮!

(1)头文件 sqlist.h 中的定义

//判空
int sqlist_empty(sqlist *head);//参数接收首地址

//判满
int sqlist_full(sqlist *head);

//清空顺序表
int sqlist_clear(sqlist *head);

//获取顺序表中有效数据长度
int sqlist_length(sqlist *head);

//显示顺序表中数据
void sqlist_display(sqlist *head);

//回收顺序表
void sqlist_destroy(sqlist *head);

(2)在 sqlist.c 中封装功能

//判空
int sqlist_empty(sqlist *head)
{
    if (-1 == head->last)
        return 1;
    else
        return 0;
    
    //或者可以使用三目运算符
    //return ((-1 == head->last) ? 1 : 0);
}

//判满
int sqlist_full(sqlist *head)
{
    return ((SIZE - 1 == head->last) ? 1 : 0);
}

//清空顺序表
int sqlist_clear(sqlist *head)
{
    head->last = -1;
}

//获取顺序表中有效数据长度
int sqlist_length(sqlist *head)
{
    return head->last + 1;
}

//显示顺序表中数据
void sqlist_display(sqlist *head)
{
    for(int i = 0; i <= head->last; i++)
        printf("%-3d",head->data[i]);
    puts(" ");
}

//回收顺序表
void sqlist_destroy (sqlist *head)//也可用二级指针
{
    free (head);
}

(3)在主函数 main.c 中调用

这些函数除了回收顺序表函数之外,在主函数中一般不会单独调用,用于辅助实现 “ 增删改查 ” 功能,不可或缺。

    //回收顺序表
    sqlist_destroy(head);
    head == NULL;

顺序表是malloc开辟的空间,需要手动释放回收,否则会导致空间泄露。

4. 顺序表 “ 增删改查 ” 功能的实现

(1)在头文件 sqlist.h 中的定义

//按位置插入数据
int sqlist_pos_insert(sqlist *head,int pos,data_t data);

//按位置删除数据
int sqlist_pos_delete(sqlist *head,int pos);

//按元素删除数据
int sqlist_data_delete(sqlist *head,data_t data);

//按位置修改数据
int sqlist_pos_update(sqlist *head,int pos,data_t data);

//按元素修改数据
int sqlist_data_update(sqlist *head,data_t old_data, data_t new_data );

//按位置查找元素
data_t sqlist_pos_search(sqlist *head,int pos);

//按元素查找位置
int sqlist_data_search(sqlist *head,data_t data);

(2)在 sqlist.c 文件中封装功能

1)按位置插入数据

//按位置插入数据
int sqlist_pos_insert(sqlist *head,int pos,data_t data)
{
    //判满
    if (sqlist_full(head))
    {
        printf("Sqlist is full! Insert failed!");
        return -1;
    }
    
    //判断pos是否有效
    int len = sqlist_length(head);
    if ((pos<0) || (pos > len)){
        printf("Insert pos is invalid!\n");
        return -1;
    }
    
    //腾出pos位置
    for(int i = head->last+1; i > pos; i--)
    {
        head->data[i] = head->data[i-1];
    }
    
    //修改数据
    head->data[pos] = data;
    head->last += 1;

    return 0;
}

2)删除数据(按元素值、按位置)

//按位置删除数据
int sqlist_pos_delete(sqlist *head,int pos)
{
    //判空(可省略)
    if (sqlist_empty(head))
    {
        printf("Sqlist is empty! Delete failed!");
        return -1;
    }

    //判断pos是否有效
    int len = sqlist_length(head);
    if ((pos<0) || (pos > len)){
        printf("Delete pos is invalid!\n");
        return -1;
    }

    //移动删除
    for(int i = pos+1; i < head->last+1; i++)
    {
        head->data[i-1] = head->data[i];
    }
    
    //将表中有效数据量-1
    head->last -= 1;
    
    return 0;
}

//按元素删除数据
int sqlist_data_delete(sqlist *head,data_t data)
{
    //判空
    if (sqlist_empty(head))
    {
        printf("Sqlist is empty! Delete failed!");
        return -1;
    }

    //删除数据
    for(int i = 0; i < head->last+1; i++)
    {
        //先找到删除元素的位置,再调用按位置删除函数(书写简便,但效率较低)
        if (data == head->data[i])
            sqlist_pos_delete(head, i);
    }
}

3)修改数据(按位置、按元素值)

//按位置修改数据
int sqlist_pos_update (sqlist *head, int pos, data_t data)
{
    //判空(可省略)
    if (sqlist_empty(head))
    {
        printf("Sqlist is empty! Update failed!");
        return -1;
    }

    //判断pos是否有效
    int len = sqlist_length(head);
    if ((pos<0) || (pos >= len)){
        printf("Update pos is invalid!\n");
        return -1;
    }

    //修改数据
    head->data[pos] = data;
}

//按元素值修改数据
int sqlist_data_update(sqlist *head, data_t old_data, data_t new_data)
{
   
    //判空
    if (sqlist_empty(head))
    {
        printf("Sqlist is empty! Update failed!");
        return -1;
    }

    //遍历寻找要修改的数据,再赋新值
    for(int i = 0; i < head->last+1; i++)
    {
        if (old_data == head->data[i])
            head->data[i] = new_data;
    }
}

4)查找数据(按位置找元素值,按元素值找位置)

//按位置查找元素
data_t sqlist_pos_search (sqlist *head, int pos) //用data_t类型接收返回的数据值
{
    //判空(可省略)
    if (sqlist_empty(head))
    {
        printf("Sqlist is empty! search failed!");
        return -1;
    }
    
    //判断pos是否有效
    int len = sqlist_length (head);
    if ((pos<0) || (pos >= len)){
        printf ("Search pos is invalid!\n");
        return -1;
    }
    
    //直接返回pos位置的数据值
    return head->data[pos];
}

//按元素查找位置
int sqlist_data_search (sqlist *head, data_t data)
{
    //假设顺序表中可能有多个相同元素
    int count = 0;

    //查找匹配元素的位置
    for (int i = 0; i < head->last+1; i++)
    {
        if (data == head->data[i])
        {
            //记录匹配元素的个数
            count++;

            //每找到一个匹配元素,打印它的位置
            printf ("%-3d", i);
        }
    }
    puts("");

    //如果计数为0,提示顺序表中没有找到匹配元素
    if (count == 0){
        printf ("Sqlist does not have this data!");
        return -1;
    }

    return 0;
}

(3)在主函数 main.c 中简单验证顺序表的 “ 增删改查 ” 功能


    //按位置插入元素
    //头插10个数
    printf("插入10个数。\n");
    int i=10;
    while(i--)
    {
        sqlist_pos_insert(head, 0, i+1);
    }

    //展示插入结果
    sqlist_display(head);

    //按位置删除元素
    printf("删除标号为3的元素。\n");
    sqlist_pos_delete(head, 3);

    sqlist_display(head);

    //按元素删除数据
    printf("删除数字2。\n");
    sqlist_data_delete(head, 2);

    sqlist_display(head);
    
    //按位置修改数据
    printf("修改标号为1的元素值为9。\n");
    sqlist_pos_update(head, 1, 9);

    sqlist_display(head);

    //按元素修改数据
    printf("修改元素值为9的元素值为0。\n");
    sqlist_data_update(head, 9, 0);

    sqlist_display(head);

    //按位置查找元素
    printf("标号为7的元素值为:%d\n",sqlist_pos_search(head, 7));

    //按元素查找位置
    printf("数值为0的元素位置标号为:");
    sqlist_data_search(head, 0);

1)运行结果如下

插入10个数。
1  2  3  4  5  6  7  8  9  10  
删除标号为3的元素。
1  2  3  5  6  7  8  9  10  
删除数字2。
1  3  5  6  7  8  9  10  
修改标号为1的元素值为9。
1  9  5  6  7  8  9  10  
修改元素值为9的元素值为0。
1  0  5  6  7  8  0  10  
标号为7的元素值为:10
数值为0的元素位置标号为:1  6 

注:在实际情况下,数据具有唯一性,可根据实际情况修改 “ 查找 ” 和 “ 修改 ” 的功能代码。

5. 总结

1. 顺序表访问、查找元素方便,但对经常进行插入和删除操作的情况不友好。

2. 若想让插入、删除功能的效率高,推荐了解链表的操作~

敬请期待下集:C语言链表的基本操作(linklist)

感谢观看!如有疑问欢迎提出!

                                                     ----香菜小猫祝这位uu天天开心----

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐