数据结构——顺序表的实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构——顺序表的实现相关的知识,希望对你有一定的参考价值。

/*
    线性结构的基本特征:

        1. 集合中必存在唯一的一个“第一元素”
        2. 集合中必存在唯一的一个“最后元素”
        3. 除最后元素之外,均有唯一的后继
        4. 除第一元素之外,均有唯一的前驱
    对线性表的基本操作:

        {结构初始化}
        InitList(&L);    //构造一个空的线性表L

        {结构的销毁}
        DestroyList(&L);    //销毁线性表L

        {引用型操作}
        ListEmpty(L);    //线性表判空
        ListLength(L);    //返回线性表长度
        PriorElem(L, cur_e, &pre_e);    //返回当前元素前驱
        NextElem(L, cur_e, &next_e);    //返回当前元素后继
        GetElem(L, i, &e);    //返回第i个元素的值
        Locate(L, e.compare());    //返回 L中第1个与e满足关系compare()的元素的位序,若不存在,返回0
        ListTraverse(L, visit());    //遍历线性表

        {加工型操作}
        ClearList(&L);    //将L重置为空表
        ListInsert(&L, i, e);    //在第i个元素之前插入新的元素e,L的长度加1
        ListDelete(&L, i, &e);    //删除L的第i个元素,并用e返回,L的长度减1
*/

#include<stdio.h>
#include<stdlib.h>

//定义数据类型
typedef int ElemType;

//顺序表的存储结构
#define LIST_INIT_SIZE 10    //线性表存储空间的初始分配量
#define LISTINCREMENT 7    //线性表存储空间的分配增量
typedef struct {
    ElemType *elem;    //存储空间基址
    int length;    //线性表当前长度
    int listsize;    //线性表当前的存储容量(以sizeof(ElemType)为单位)
}SqList;

//声明,指针函数
bool (*compare)(ElemType e1, ElemType e2);
void (*visit)(ElemType e);

//声明,辅助函数
bool equals(ElemType e1, ElemType e2);
void visitElem(ElemType e);

//声明,对线性表的基本操作
//将有返回值的方法写成ElemType f(),即return (ElemType)i,可能效果更好一些
bool InitList(SqList &L);    //初始化一个空表
bool DestroyList(SqList &L);    //销毁线性表
bool ListEmpty(SqList L);    //线性表判空
int ListLength(SqList L);    //线性表长度
void PriorElem(SqList L, ElemType cur_e, ElemType &pre_e);    //返回当前元素的前驱
void NextElem(SqList L, ElemType cur_e, ElemType &next_e);    //返回当前元素的后继
void getElem(SqList L, int i, ElemType &e);    //返回第i个元素的值,0表示第一个元素
void getTail(SqList L, ElemType &e);    //返回第最后一个元素
void getHead(SqList L, ElemType &e);    //返回第一个元素
int LocateElem(SqList L, ElemType e, bool (*compare)(ElemType e1, ElemType e2));
                                            //返回线性表中与e满足compare关系的第一个元素的位置
void ListTraverse(SqList L, void (*visit)(ElemType e));    //遍历线性表
void ClearList(SqList &L);    //将线性表置空
void ListInsert(SqList &L, int i, ElemType e);    //在第i个元素之前插入
void AppendTail(SqList &L, ElemType e);    //在表尾插入,即插入为最后一个元素
void AppendHead(SqList &L, ElemType e);    //在表头插入,即插入为第一个元素
void ListDelete(SqList &L, int i, ElemType &e);    //删除第i个元素,并用返回删除的元素
void DeleteTail(SqList &L, ElemType &e);    //删除表尾元素,即删除最后一个元素
void DeleteHead(SqList &L, ElemType &e);    //删除表头元素,即删除第一个元素

//测试模块
int main(){
    SqList L;
    InitList(L);

    //给线性表中插入元素,遍历
    for (int i = 1; i < 18; i++){
        if (i % 3 == 0)
            AppendTail(L, i);
        else if (i % 4 == 0)
            ListInsert(L, 3, i);
        else
            AppendHead(L, i);
    }    
    ListTraverse(L, visitElem);
    printf("\n\n");
    
    //求第一个元素前驱(返回错误),除第一个元素外其他元素的前驱,线性表中不存在的元素的前驱(
    //返回错误)
    ElemType e;
    ElemType e1;
    PriorElem(L, 12, e);
    printf("12的前驱是:%d\n\n", e);
    getHead(L, e1);
    PriorElem(L, e1, e);
    printf("%d的前驱是:%d\n\n", e1, e);
    PriorElem(L, 21, e);
    printf("21的前驱是:%d\n\n", e);

    //求最后一个元素后继(返回错误),除最后一个元素外其他元素后继,线性表中不存在的元素的后继(
    //返回错误)
    NextElem(L, 12, e);
    printf("12的后继是:%d\n\n", e);
    getTail(L, e1);
    NextElem(L, e1, e);
    printf("%d的后继是:%d\n\n", e1, e);
    NextElem(L, 21, e);
    printf("21的后继是:%d\n\n", e);

    //删除第一个元素,删除最后一个元素,删除其他元素,删除超出线性表长度的元素(返回错误)
    DeleteHead(L, e);
    printf("删除的元素是:%d\n\n", e);
    DeleteTail(L, e);
    printf("删除的元素是:%d\n\n", e);
    ListDelete(L, 3, e);
    printf("删除的元素是:%d\n\n", e);
    ListDelete(L, 21, e);
    printf("删除的元素是:%d\n\n", e);
    ListTraverse(L, visitElem);
    printf("\n\n");

    system("pause");
    return 0;
}

//各函数定义模块
bool equals(ElemType e1, ElemType e2){
    if (e1 == e2)
        return true;
    else return false;
}

void visitElem(ElemType e){
    printf("%4d", e);
}

bool InitList(SqList &L){    //初始化一个空表
    L.elem = (ElemType*)malloc(sizeof(ElemType)*LIST_INIT_SIZE);
    if (!L.elem)
        return false;
    L.length = 0;
    L.listsize = LIST_INIT_SIZE;
    return true;
}

bool DestroyList(SqList &L){    //销毁线性表
    if (L.elem){
        free(L.elem);
        return true;
    }
    return false;
}

bool ListEmpty(SqList L){    //线性表判空
    if (L.length == 0)
        return true;
    else return false;
}

int ListLength(SqList L){    //线性表长度
    return L.length;
}

void PriorElem(SqList L, ElemType cur_e, ElemType &pre_e){    //返回当前元素的前驱
    int curPos = LocateElem(L, cur_e, equals);
    if (curPos > 0){
        pre_e = L.elem[curPos - 1];
    }
    else{
        if (curPos == 0){
            printf("当前元素是线性表中第一个元素,没有后继\n");
            pre_e = -1;
        }
        else{
            printf("线性表中不存在该元素!\n");
            pre_e = -1;
        }
    }
}

void NextElem(SqList L, ElemType cur_e, ElemType &next_e){    //返回当前元素的后继
    int curPos = LocateElem(L, cur_e, equals);
    if (curPos > -1 && curPos < L.length - 1){
        next_e = L.elem[curPos + 1];
    }
    else{
        if (curPos == L.length - 1){
            printf("当前元素是线性表中最后一个元素,没有前驱\n");
            next_e = -1;
        }
        else{
            printf("线性表中不存在该元素!\n");
            next_e = -1;
        }
    }
}

void getElem(SqList L, int i, ElemType &e){    //返回第i个元素的值,0表示第一个元素
    if (i<1 || i>L.length){
        printf("当前索引超出线性表的范围!\n");
        return;
    }
    e = L.elem[i - 1];
}

void getTail(SqList L, ElemType &e){    //返回第最后一个元素
    getElem(L, L.length, e);
}

void getHead(SqList L, ElemType &e){    //返回第一个元素
    getElem(L, 1, e);
}

int LocateElem(SqList L, ElemType e, bool(*compare)(ElemType e1, ElemType e2)){
                                            //返回线性表中与e满足compare关系的第一个元素的位置
    for (int i = 0; i < L.length; i++){
        if (compare(e, L.elem[i]))
            return i;
    }
    return -1;
}

void ListTraverse(SqList L, void(*visit)(ElemType e)){    //遍历线性表
    for (int i = 0; i < L.length; i++){
        if (i % 4 == 0)
            printf("\n");
        visit(L.elem[i]);
    }
}

void ClearList(SqList &L){    //将线性表置空
    L.length = 0;
}

void ListInsert(SqList &L, int i, ElemType e){    //在第i个元素之前插入
    //判断插入的位置是否合法
    if (i<1 || i>L.length + 1){
        printf("插入的位置不合法!\n");
        return;
    }
    //判断链表的存储空间是否足够
    if (L.length >= L.listsize){
        ElemType *newElem = (ElemType*)realloc(L.elem, (L.listsize + LISTINCREMENT)*sizeof(ElemType));
        if (!newElem)
            return;
        L.elem = newElem;
        L.listsize += LISTINCREMENT;
    }

    ElemType *iPos = &L.elem[i - 1];
    ElemType *tailPos = L.elem + L.length - 1;
    for (; tailPos >= iPos; tailPos--)
        *(tailPos + 1) = *tailPos;
    *iPos = e;
    L.length++;
}

void AppendTail(SqList &L, ElemType e){    //在表尾插入,即插入为最后一个元素
    ListInsert(L, L.length + 1, e);
}

void AppendHead(SqList &L, ElemType e){    //在表头插入,即插入为第一个元素
    ListInsert(L, 1, e);
}

void ListDelete(SqList &L, int i, ElemType &e){    //删除第i个元素,并用返回删除的元素
    //判断删除的位置是否合法
    if (i<1 || i>L.length){
        printf("删除的位置不合法!\n");
        e = -1;
        return;
    }
    ElemType *iPos = &L.elem[i - 1];
    ElemType *tailPos = L.elem + L.length - 1;
    e = *iPos;
    for (; iPos <= tailPos; iPos++)
        *iPos = *(iPos + 1);
    L.length--;
}

void DeleteTail(SqList &L, ElemType &e){    //删除表尾元素,即删除最后一个元素
    ListDelete(L, L.length, e);
}
void DeleteHead(SqList &L, ElemType &e){    //删除表头元素,即删除第一个元素
    ListDelete(L, 1, e);
}

不积跬步,无以至千里;不积小流,无以成江海。从简单的开始,坚持着。

以上是关于数据结构——顺序表的实现的主要内容,如果未能解决你的问题,请参考以下文章

Java数据结构(线性表)--线性表的顺序存储及其实现

顺序表的java实现

数据结构算法C语言实现---2.3线性表的顺序表示和实现

线性表的链式存储(C代码实现)

数据结构 c语言版 ——顺序表的查找、插入与删除

数据结构《一》顺序表的实现