【C语言】静态顺序表和动态顺序表的实现

静态顺序表

定义一张顺序表也就是在内存中开辟一段连续的存储空间,并给它一个名字进行标识。只有定义了一个顺序表,才能利用该顺序表存放数据元素,也才能对该顺序表进行各种操作。

有两种定义顺序表的方法:一是静态地定义一张顺序表;二是动态地生成一张顺序表。

静态地定义一张顺序表的方法与定义一个数组的方法类似。可以描述如下:

#define MAX_SIZE 100
typedef int DataType;
typedef struct SeqList
{
    DataType array[MAX_SIZE];
    size_t size;
}SeqList;

静态顺序表的一些与运算实现如下:


SeqList.h

#pragma once
#define _SEQ_LIST_
#ifdef _SEQ_LIST_

#include <stdio.h>
#include <string.h>//memset
#include <assert.h>//assert

#define MAX_SIZE 100
typedef int DataType;
typedef struct SeqList
{
    DataType array[MAX_SIZE];
    size_t size;
}SeqList;

typedef enum TAG
{
    TURE,//找到对应元素
    FALSE,//未找到对应元素
}TAG;
TAG tag;
typedef struct FindRet
{
    TAG IsFind;//反应是否找到对应的元素
    size_t index;//找到的元素的下标
}FindRet;
FindRet ret;
void InitSeqList(SeqList* pSeq);//初始化
void PrintSeqList(SeqList* pSeq);//显示数据
void ExplandCapicity(SeqList *pSeq);//扩大容量

void PushBack(SeqList* pSeq, DataType x);//从尾插入数据
void PopBack(SeqList* pSeq);//从尾删除数据

void PushFront(SeqList* pSeq, DataType x);//从头插入数据
void PopFront(SeqList* pSeq);//从头删除数据

void Insert(SeqList* pSeq, size_t index, DataType x);//在下标为index处插入数据
void Modified(SeqList* pSeq, size_t index, DataType x);//修改下标为index的数据为x
void Removed(SeqList* pSeq, size_t index);//删除下标为index的数据

FindRet Find(SeqList *pSeq, DataType x, size_t index);//查找数据
TAG Erase(SeqList *pSeq, DataType x, TAG all);//all=FALSE时删除第一个出现的数据
                                             //all=TURE时删除一个所有相同的数据
#endif

SeqList.c

#include "seqlist.h"
void InitSeqList(SeqList *pSeq)//初始化
{
    assert(pSeq);
    memset(pSeq->array, 0,MAX_SIZE*sizeof(DataType));
    pSeq->size = 0;
}
void PrintSeqList(SeqList* pSeq)//显示数据
{
    size_t i = 0;
    assert(pSeq);
    for (i = 0; i < pSeq->size; i++)
    {
        printf("%d ", pSeq->array[i]);
    }
}
void PushBack(SeqList* pSeq, DataType x)//从尾插入数据
{
    assert(pSeq);
    if (pSeq->size > MAX_SIZE-1)
    {
        printf("The seqlist is Full\n");
        return;
    }
    pSeq->array[pSeq->size++] = x;
}
void PopBack(SeqList* pSeq)//从尾删除数据
{
    assert(pSeq);
    if (pSeq->size < 1)
    {
        printf("The seqlist is empty\n");
        return;
    }
    --pSeq->size;
    //或者pSeq->array[--pSeq->size] = 0;
}
void PushFront(SeqList* pSeq, DataType x)//从头插入数据
{
    int i = pSeq->size-1;
    assert(pSeq);
    if (pSeq->size > MAX_SIZE-1)
    {
        printf("The seqlist is Full\n");
        return;
    }
    for (; i >= 0; i--)
    {
        pSeq->array[i+1] = pSeq->array[i];
    }
    pSeq->array[0] = x;
    pSeq->size++;
}
void PopFront(SeqList* pSeq)//从头删除数据
{
    size_t i = 0;
    assert(pSeq);
    if (pSeq->size < 1)
    {
        printf("The seqlist is empty\n");
        return;
    }
    for (i = 0; i < pSeq->size - 1; i++)
    {
        pSeq->array[i] = pSeq->array[i + 1];
    }
    pSeq->size--;
}
void Insert(SeqList* pSeq, size_t index, DataType x)//在index处随机插入数据
{
    size_t i = pSeq->size;
    assert(pSeq);
    if (index > MAX_SIZE-1)
    {
        printf("The seqlist is Full\n");
        return;
    }
    for (; i > index; i--)
    {
        pSeq->array[i] = pSeq->array[i-1];
    }
    pSeq->array[index] = x;
    pSeq->size++;
}
void Modified(SeqList* pSeq, size_t index, DataType x)//随机修改数据(修改index处的值)
{
    assert(pSeq);
    assert(index<pSeq->size);
    pSeq->array[index] = x;
}
void Removed(SeqList* pSeq, size_t index)//随机删除数据
{
    size_t i = index;
    assert(pSeq);
    assert(index<pSeq->size);
    for (; i < pSeq->size - 1; i++)
    {
        pSeq->array[i] = pSeq->array[i + 1];
    }
    pSeq->size--;
}
FindRet Find(SeqList *pSeq, DataType x,size_t index)//增加了形参index,可以记录每次查找的
{                                                   //位置,提高了效率
    assert(pSeq);
    ret.IsFind = FALSE;
    for (; index < pSeq->size; index++)
    {
        if (pSeq->array[index] == x)
        {
            ret.index = index;
            ret.IsFind = TURE;
            return ret;
        }
    }
    return ret;
}
TAG Erase(SeqList *pSeq, DataType x,TAG all)//all=FALSE表示删除一个第一次出现的数据
{                                           //all=TRUE表示删除一个重复的数据
    assert(pSeq);
    TAG success = FALSE;
    ret = Find(pSeq,x,0);
    while (ret.IsFind == TURE)
    {
        success = TURE;
        Removed(pSeq,ret.index);
        if (all == TURE)//表示删除一个数据
        {
            break;
        }
        ret = Find(pSeq,x,ret.index);
    }
    return success;
}
void Test()
{
    SeqList s;
    InitSeqList(&s);
    printf("The PushBack is:\n");
    PushBack(&s, 3);
    PushBack(&s ,5);
    PushBack(&s, 4);
    PushBack(&s, 3);
    PushBack(&s, 2);
    PushBack(&s, 3);
    PushBack(&s, 3);
    PushBack(&s, 3);
    PushBack(&s, 1);
    PrintSeqList(&s);
    printf("\nPopBack is:\n");
    PopBack(&s);
    PrintSeqList(&s);
    printf("\nPushFront 10,20 is:\n");
    PushFront(&s,10);
    PushFront(&s,20);
    PrintSeqList(&s);
    printf("\nPopFront 20 is:\n");
    PopFront(&s);
    PrintSeqList(&s);
    printf("\nInsert 99 is:\n");
    Insert(&s,2,99);
    PrintSeqList(&s);
    printf("\nModified 99 to 88 is :\n");
    Modified(&s,2,88);
    PrintSeqList(&s);
    printf("\nremoved 88 is:\n");
    Removed(&s, 2);
    PrintSeqList(&s);
    printf("\nFind %d index is :\n",5);
    ret = Find(&s, 5,0);
    if (ret.IsFind == TURE)
    {
        printf("%d\n",ret.index);
    }
    else if (ret.IsFind == FALSE)
    {
        printf("is not exit\n");
    }
    printf("Erase 3 is :\n");
    Erase(&s,3,FALSE);
    PrintSeqList(&s);
}
int main()
{
    Test();
    return 0;
}



动态地生成一张顺序表的方法可描述如下:

#define EXPLANDSIZE 2
typedef int DataType;
typedef struct SeqList
{
    DataType *elem;//指向当前空间
    size_t size;//当前有效数据的长度
    size_t capicity;//当前容量
}SeqList;

动态顺序表的一些与运算实现如下:


SeqList.h


#pragma once
#define _SEQ_LIST_
#ifdef _SEQ_LIST_

#include <stdio.h>//size_t
#include <stdlib.h>//malloc
#include <assert.h>//assert
#include <string.h>//memcpy

#define EXPLANDSIZE 2
typedef int DataType;
typedef struct SeqList
{
    DataType *elem;//指向当前空间
    size_t size;//当前有效数据的长度
    size_t capicity;//当前容量
}SeqList;

typedef enum TAG
{
    TURE,
    FALSE,
}TAG;
TAG tag;
typedef struct FindRet
{
    TAG Isfind;
    size_t index;
}FindRet;
FindRet ret;
void InitSeqList(SeqList* pSeq);//初始化
void PrintSeqList(SeqList* pSeq);//显示数据
void ExplandCapicity(SeqList *pSeq);//扩大容量

void PushBack(SeqList* pSeq, DataType x);//从尾插入数据
void PopBack(SeqList* pSeq);//从尾删除数据

void PushFront(SeqList* pSeq, DataType x);//从头插入数据
void PopFront(SeqList* pSeq);//从头删除数据

void Insert(SeqList* pSeq, size_t index, DataType x);//在下标为index处插入数据
void Modified(SeqList* pSeq, size_t index, DataType x);//修改下标为index的数据为x
void Removed(SeqList* pSeq, size_t index);//删除下标为index的数据

FindRet Find(SeqList *pSeq, DataType x,size_t index);//查找数据
TAG Erase(SeqList *pSeq, DataType x,TAG all);//all=FALSE时删除第一个出现的数据
                                             //all=TURE时删除一个所有相同的数据
void BubbleSort(SeqList *pSeq);//冒泡排序
void SeleSort(SeqList *pSeq);//选择排序
void swap(DataType *left,DataType *right);//交换值
FindRet BinarySearch(SeqList *pSeq, DataType X);//二分查找
#endif

SeqList.c

#include "seqListdongtai.h"

void InitSeqList(SeqList* pSeq)//初始化
{
    assert(pSeq);
    pSeq->elem = (DataType *)malloc(EXPLANDSIZE * sizeof(DataType));
    pSeq->capicity = EXPLANDSIZE;
    pSeq->size = 0;//表示有效数据
}
void ExplandCapicity(SeqList *pSeq)
{
    if (pSeq->size == pSeq->capicity)
    {
        //pSeq->capicity += ExplandSize;
        //DataType *newbase = (DataType *)malloc(pSeq->capicity * sizeof(DataType));
        DataType *newbase = (DataType *)malloc(pSeq->capicity*2 * sizeof(DataType));
        pSeq->capicity *= 2;
        memcpy(newbase, pSeq->elem, pSeq->size * sizeof(DataType));
        free(pSeq->elem);
        pSeq->elem = newbase;
    }
}
FindRet Find(SeqList *pSeq, DataType x, size_t index)//查找数据
{
    assert(pSeq);
    assert(index<pSeq->size);
    ret.Isfind = FALSE;
    for (; index < pSeq->size; index++)
    {
        if (pSeq->elem[index] == x)
        {
            ret.index = index;
            ret.Isfind = TURE;
            return ret;
        }
    }
    return ret;
}

void PrintSeqList(SeqList* pSeq)//显示数据
{
    assert(pSeq);
    size_t i = 0;
    for (; i < pSeq->size; i++)
    {
        printf("%d ",pSeq->elem[i]);
    }
}
void PushBack(SeqList* pSeq, DataType x)//从尾插入数据
{
    assert(pSeq);
    ExplandCapicity(pSeq);
    pSeq->elem[pSeq->size++] = x;
}
void PopBack(SeqList* pSeq)//从尾删除数据
{
    assert(pSeq);
    if (pSeq->size > 0)
    {
        pSeq->size--;
    }
}
void PushFront(SeqList* pSeq, DataType x)//从头插入数据
{
    assert(pSeq);
    size_t i = pSeq->size;
    ExplandCapicity(pSeq);
    for (; i > 0; i--)
    {
        pSeq->elem[i] = pSeq->elem[i - 1];
    }
    pSeq->elem[0] = x;
    pSeq->size++;
}
void PopFront(SeqList* pSeq)//从头删除数据
{
    assert(pSeq);
    assert(pSeq->size != 0);
    size_t i = 0;
    for (; i < pSeq->size - 1; i++)
    {
        pSeq->elem[i] = pSeq->elem[i + 1];
    }
    pSeq->size--;
}
void Insert(SeqList* pSeq, size_t index, DataType x)//随机插入数据
{
    assert(pSeq);
    assert(index<pSeq->size);
    size_t i = pSeq->size;
    ExplandCapicity(pSeq);
    for (; i > index; i--)
    {
        pSeq->elem[i] = pSeq->elem[i - 1];
    }
    pSeq->elem[index] = x;
    pSeq->size++;
}
void Modified(SeqList* pSeq, size_t index, DataType x)//随机修改数据
{
    assert(pSeq);
    assert(index<pSeq->size);
    pSeq->elem[index] = x;
}
void Removed(SeqList* pSeq, size_t index)//随机删除数据
{
    assert(pSeq);
    assert(index<pSeq->size);
    size_t i = index;
    for (; i < pSeq->size-1; i++)
    {
        pSeq->elem[i] = pSeq->elem[i + 1];
    }
    pSeq->size--;
}
TAG Erase(SeqList *pSeq, DataType x, TAG all)//删除一个所有相同的数据
{
    assert(pSeq);
    tag = FALSE;
    ret = Find(pSeq,5,0);
    while (ret.Isfind == TURE)
    {
        tag = TURE;
        Removed(pSeq,ret.index);
        if (all == FALSE)
        {
            break;
        }
        ret = Find(pSeq,5,ret.index);
    }
    return tag;
}
void swap(DataType *left, DataType *right)//交换值
{
    DataType tmp = *left;
    *left = *right;
    *right = tmp;
}
void BubbleSort(SeqList *pSeq)//冒泡排序
{
    int flag = 0,count = 0;
    size_t index = 0,end = 0;
    assert(pSeq);
    for (index = 0; index < pSeq->size - 1; index++)//循环比较
    {
        for (end = 0; end < (pSeq->size - 1) - index; end++)
        {
            count++;
            if (pSeq->elem[end] > pSeq->elem[end + 1])
            {
                int tmp = pSeq->elem[end];
                pSeq->elem[end] = pSeq->elem[end + 1];
                pSeq->elem[end + 1] = tmp;
                flag = 1;
            }
        }
        if (flag == 0)
        {
            break;
        }
        flag = 0;
    }
    printf("冒泡次数:%d\n", count);
}
void SeleSort(SeqList *pSeq)//选择排序
{
    size_t index,minindex = 0;
    size_t begin = 0;
    for (begin = 0; begin < pSeq->size - 1;begin++)
    {
        minindex = begin;
        for (index = begin+1; index < pSeq->size; index++)
        {
            if (pSeq->elem[index] < pSeq->elem[minindex])
            {
                minindex = index;
            }
        }
        if (minindex != index)
        {
            swap(pSeq->elem + minindex, pSeq->elem + begin);
        }
    }
}
FindRet BinarySearch(SeqList *pSeq, DataType x)//二分查找
{
    assert(pSeq);
    int left, right, mid;
    left = 0;
    right = pSeq->size - 1;
    ret.Isfind = FALSE;
    while (left <= right)
    {
        mid = left +((right-left) / 2);
        if (pSeq->elem[mid] == x)
        {
            ret.Isfind = TURE;
            ret.index = mid;
            return ret;
        }
        else if (pSeq->elem[mid] < x)
        {
            left = mid + 1;
        }
        else
        {
            right = mid - 1;
        }
    }
    return ret;
}
int main()
{
    SeqList s;
    InitSeqList(&s);//初始化
    printf("PushBack is\n");
    PushBack(&s, 6);//从尾插入数据
    PushBack(&s, 5);
    PushBack(&s, 4);
    PushBack(&s, 5);
    PushBack(&s, 5);
    PushBack(&s, 3);
    PushBack(&s, 5);
    PushBack(&s, 2);
    PushBack(&s, 1);
    PrintSeqList(&s);
    printf("\nPopBack 1 is :\n");
    PopBack(&s);//从尾删除数据
    PrintSeqList(&s);
    printf("\nPushFront 99 is:\n");
    PushFront(&s,99);//从前插入数据
    PrintSeqList(&s);
    printf("\nPopFront 99 is:\n");
    PopFront(&s);//从前删除数据
    PrintSeqList(&s);
    printf("\nInsert 88 is:\n");
    Insert(&s,1,88);//在下标为1的地方插入数据
    PrintSeqList(&s);
    printf("\nModified 5 is :\n");
    Modified(&s,2,55);//修改下标为2的的数据为55
    PrintSeqList(&s);
    printf("\nRemove 4 is:\n");
    Removed(&s,3);//删除下标为3的数据
    PrintSeqList(&s);
    printf("\nErase 5 is:\n");
    Erase(&s,5,TURE);//删除所有5
    PrintSeqList(&s);
    printf("\nBubbleSort:\n");
    BubbleSort(&s);//冒泡排序
    PrintSeqList(&s);
    printf("\n");
    BubbleSort(&s);//再次冒泡排序
    PrintSeqList(&s);
    printf("\nSeleSort:\n");
    SeleSort(&s);//选择排序
    PrintSeqList(&s);
    printf("\nBinarySearch 88 is :\n");
    BinarySearch(&s, 88);//二分查找
    if (ret.Isfind == TURE)
    {
        printf("下标为:%d\n",ret.index);
    }
    else
    {
        printf("Search is failed\n");
    }
    return 0;
}


线性表优点是:

无须为表示表中元素之间的逻辑关系增加额外的存储空间;

可以方便地随机访问表中任一位置的元素。

缺点是:

插入和删除运算不方便,除表尾的位置外,在表的其他位置上进行插入或删除操作都必须移动大量元素,其效率较低;

由于数组要求占用连续的存储空间,存储分配只能预先进行静态分配。因此,当表长变化较大时,难以确定数组的合适的大小。确定大了将造成浪费。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-27 23:57:17

【C语言】静态顺序表和动态顺序表的实现的相关文章

静态顺序表和动态顺序表

实现一个静态顺序表,首先,要定义一个保存数据的数组,保存在结构体中,用size来存储数组中的元素个数, typedef struct SeqList { DataType array[MAX_SIZE]; size_t size; }SeqList; 首先来实现一下静态顺序表的初始化函数,可以借用系统的memset函数来实现,开辟一块空间全部初始化为0,没有存入数据所以size也为0 void InitSeqList(SeqList *pSeq) { assert(pSeq); memset(p

C语言:【动态顺序表】动态顺序表的初始化、打印、尾插PushBack、尾删PopBack

#include<stdio.h> #include<stdlib.h> #include<assert.h> #include<string.h> #include<malloc.h> typedef int DateType; typedef struct SeqList {     DateType *arr;     size_t capacility;     size_t size; }SeqList; //创建空间 void Che

c实现的动态顺序表

第一篇文章中用c实现了静态顺序表,但是使用静态顺序表还有不足的地方.当我们需要存储的数据很少时,如果静态顺序表的数组容量较大就会造成空间的浪费:当我们需要存储的数据很多时,如果静态顺序表的数组容量较小可能就会造成数据丢失.所以一般情况我们应该尽量把顺序表实现成动态的.需要多大容量就开辟多大容量. 静态顺序表和动态顺序表只有以下函数不同: 1.定义结构体时,多定义一个capacity,并对capacity进行初始化和增加大小的设置: #define INIT_CAPACITY 3 #define 

反射动态建表

SQLiteHelper定义一个接口SQLiteDataTable,里边重写onCreate和onUpgrade方法.在SQLiteDaoBase基类去实现这个SQLiteDataTable接口方法. 然后UserDao继承了SQLiteDaoBase这个基类,实现抽象类里的oncreate和onUpgrade两个方法,在oncreate方法里创建user表,写sql语句. 在SQLiteHelper里的onCreate方法里通过反射获得任意一个实现了SQLiteDataTable接口的实例,再

动态顺序表(可分配内存空间)

<strong style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">前几天写了一个静态顺序表,但是觉得一开始开辟很大一部分空间却不一定可以完全用得上,会造成很大的内存浪费,于是写了一个可以自动开辟内存空间的动态顺序表作为改进.</strong> "DynamicSeqllist.h" #pragma once #def

动态顺序表 与 双向链表的模板类

//////////////////////////////////////////////////////////////////////// /////////////////////泛型编程之动态顺序表的模板///////////////////////// //////////////////////////////////////////////////////////////////////// #include<iostream> #include<string> u

基于静态分配的数组的顺序表(兼具Boost单元测试)

首先,我们来搞明白几个概念吧(参考自网站数据结构及百度百科). 线性表 线性表是最基本.最简单.也是最常用的一种数据结构.线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的.线性表的逻辑结构简单,便于实现和操作.在实现线性表数据元素的存储方面,一般可用顺序存储结构和链式存储结构两种方法. 顺序表 用顺序存储方法存储的线性表简称为顺序表(Sequential List).顺序表的存储方法是把线性表的结点按逻辑次序依次存放在一组地址连续的存储单元

Java语言描述顺序表类,顺序表类的基本操作实现

数据结构(Java版)ch2 线性表的顺序存储(顺序表) 线性表的抽象数据Java接口描述如下: package ch2; /** * 线性表的抽象数据接口,用Java语言描述线性表的这些功能! * @author 房廷飞 * */ public interface IList { public void clear(); //将线型表置成空表 public boolean isEmpty(); //判断是不是空表 public int length(); //返回线性表的长度 public O

算法系列笔记5(扩展数据结构-动态顺序统计和区间树)

在编程中,我们往往使用已有的数据结构无法解决问题,这是不必要急着创建新的数据结构,而是在已有数据结构的基础上添加新的字段.本节在上一次笔记红黑树这一基础数据结构上进行扩展,得出两个重要的应用-动态顺序统计和区间树. 动态顺序统计 在算法系列笔记2中我们在线性时间内完成了静态表的顺序统计,而这里我们在红黑树上进行扩展,在O(lgn)时间内完成该操作,主要包括返回第i 排名的元素os_select(i)和给定一个元素x,返回其排名(os_rank(x)). 思想:添加新项:在红黑树的结点上记录下该结