数据结构实验二之线性表(上)

实验题1:实现顺序表的各种基本运算的算法

题目描述

编写一个程序sqlist.cpp,实现顺序表的各种基本运算和整体建表异法(假设顺序表的元素类型 Elem Type为char),并在此基础上设计一个程序exp2-1.cpp完成以下功能。

(1)初始化顺序表L。

(2)依次插入元素a、b、c、d、e。

(3)输出顺序表L。

(4)输出顺序表L的长度。

(5)判断顺序表L 是否为空。

(6)输出顺序表L的第3个元素。

(7)输出元素a的位置。

(8)在第4个元素的位置上插入元素f。

(9)输出顺序表L。

(10)删除顺序表L的第3个元素。

(11)输出顺序表L。

(12)释放顺序表L。

sqlist.cpp程序,其中包含如下函数:

· InitList(SqList*&L):初始化顺序表L。

· DestroyList(SqList*L):释放顺序表L。

· ListEmpty(SqList*L.):判断顺序表L是否为空表。

· ListLength(SqList *L):返回顺序表L中的元素个数。

· DispList(SqList*L):输出顺序表L。

·GetElem(SqList *L,int i,ElemType &e):获取顺序表L中的第i个元素。

· LocateElem(SqList *L.ElemType e):在顺序表L中查找元素e。

· ListInsert(SqList*&L,inti,ElemType e):在顺序表L中的第i个位置上插入元素c。

· ListDelete(SqList*&L,int i,ElemType &e):从顺序表L中删除第i个元素。

运行代码

sqlict.cpp
#include <iostream>
#include<malloc.h>
using namespace std;
#define MAXSIZE 100
typedef char ElemType;
typedef struct {
    ElemType data[MAXSIZE];
    int length;
} SqList;//表明表的类型
//整体建立顺序表
void GreateList(SqList* L, ElemType a[], int n) {
    L = (SqList*)malloc(sizeof(SqList));
    for (int i = 0; i < n; i++)
        L->data[i] = a[i];
    L->length = n;
}
// 初始化顺序表 L
void InitList(SqList* L) {
    L = (SqList*)malloc(sizeof(SqList));
    L->length = 0;
}
// 释放顺序表 L
void DestroyList(SqList*& L) {
    delete L;
}
// 判断顺序表 L 是否为空表
bool ListEmpty(SqList* L) {
    return L->length == 0;
}
// 返回顺序表 L 中的元素个数
int ListLength(SqList* L) {
    return L->length;
}
// 输出顺序表 L
void DispList(SqList* L) {
    for (int i = 0; i < L->length; i++) {
        cout << L->data[i] << " ";
    }
    cout << endl;
}
// 获取顺序表 L 中的第 i 个元素
bool GetElem(SqList* L, int i, ElemType& e) {
    if (i < 1 || i > L->length) {
        return false;
    }
    e = L->data[i - 1];
    return true;
}
// 在顺序表 L 中查找元素 e
int LocateElem(SqList* L, ElemType e) {
    for (int i = 0; i < L->length && L->data[i] != e; i++) {
        if (i > L->length)
            return 0;
        else
            return i + 1;
    }
    return 0;
}
// 在顺序表 L 中的第 i 个位置上插入元素 e
bool ListInsert(SqList*& L, int i, ElemType e) {
    if (i < 1 || i > L->length + 1 || L->length == MAXSIZE) {
        return false;
    }
    for (int j = L->length; j >= i; j--) {
        L->data[j] = L->data[j - 1];
    }
    L->data[i - 1] = e;
    L->length++;
    return true;
}
// 从顺序表 L 中删除第 i 个元素
bool ListDelete(SqList*& L, int i, ElemType& e) {
    if (i < 1 || i > L->length) {
        return false;
    }
    e = L->data[i - 1];
    for (int j = i; j < L->length; j++) {
        L->data[j - 1] = L->data[j];
    }
    L->length--;
    return true;
}
 exp2-1.cpp
#include <iostream>
#include "sqlist.cpp"
using namespace std;
int main() {
    SqList* L;
    cout << "顺序表的基本运算如下:" << endl;
    cout << "  (1)初始化顺序表L:" << endl;
    InitList(L);
    cout << "  (2)依次插入元素a,b,c,d,e:" << endl;
    ListInsert(L, 1, 'a');
    ListInsert(L, 2, 'b');
    ListInsert(L, 3, 'c');
    ListInsert(L, 4, 'd');
    ListInsert(L, 5, 'e');
        cout << "  (3)输出顺序表L:";
    DispList(L);
    cout << "  (4)顺序表 L 的长度为:" << ListLength(L) << endl;
    cout << "  (5)判断顺序表 L 是否为空:" << (ListEmpty(L) ? "是" : "否") << endl;
    ElemType e;
    GetElem(L, 3, e);
    cout << "  (6)顺序表 L 的第 3 个元素为:" << e << endl;
    cout << "  (7)元素 a 的位置为:" << LocateElem(L, 'a') << endl;
    cout << "  (8)在第4个元素位置上插入元素f" << endl;
    ListInsert(L, 4, 'f');
    cout << "  (9)插入元素 f 后的顺序表 L 为:";
    DispList(L);
    cout << "  (10)删除第 3 个元素:" << endl;
    ListDelete(L, 3, e);
    cout << "  (11)输出顺序表 L :";
    DispList(L);
    cout << "  (12)释放顺序表 L :" << endl;
    DestroyList(L);
    return 1;
}

代码结果与思路

  1. GreateList 函数:该函数用于整体建立顺序表。

    • 首先动态分配一个 SqList 类型的内存空间,并将其地址赋给传入的指针 L
    • 然后通过循环将给定的数组 a 中的元素逐个复制到新创建的顺序表 L 的 data 数组中。
    • 最后设置顺序表的长度为传入的数组元素个数 n
  2. InitList 函数:用于初始化顺序表。

    • 动态分配一个 SqList 类型的内存空间,并将其地址赋给传入的指针 L
    • 将顺序表的长度初始化为 0。
  3. DestroyList 函数:释放顺序表所占用的内存空间。使用 delete 操作符释放传入的指针 L 所指向的内存。

  4. ListEmpty 函数:判断顺序表是否为空表。通过检查顺序表的长度是否为 0 来确定顺序表是否为空。

  5. ListLength 函数:返回顺序表中的元素个数。直接返回顺序表的长度属性。

  6. DispList 函数输出顺序表中的所有元素。通过循环遍历顺序表的 data 数组,逐个输出其中的元素。

  7. GetElem 函数:获取顺序表中指定位置的元素。

    • 首先检查传入的位置参数 i 是否合法(大于等于 1 且小于等于顺序表长度)。
    • 如果合法,将顺序表中对应位置的元素赋值给传入的引用参数 e,并返回 true;否则返回 false
  8. LocateElem 函数

    • 在顺序表中查找指定元素的位置。
    • 通过循环遍历顺序表的 data 数组,逐个比较元素与查找的目标元素 e
    • 如果找到目标元素,返回其位置(从 1 开始计数);如果遍历完整个顺序表都未找到目标元素,返回 0。
  9. ListInsert 函数:在顺序表的指定位置插入元素。

    • 首先检查插入位置参数 i 是否合法(大于等于 1 且小于等于顺序表长度加 1,同时顺序表未满)。
    • 如果合法,通过循环将插入位置及之后的元素向后移动一位,为新元素腾出位置。
    • 将新元素插入到指定位置,更新顺序表的长度,并返回 true;否则返回 false
  10. ListDelete 函数 :  从顺序表中删除指定位置的元素。首先检查删除位置参数 i 是否合法(大于等于 1 且小于等于顺序表长度)。如果合法,将指定位置的元素赋值给传入的引用参数 e。通过循环将删除位置之后的元素向前移动一位,覆盖被删除的元素。更新顺序表的长度,并返回 true;否则返回 false

实验题2:实现单链表的各种基本运算的算法

题目描述

编写一个程序Linklist.cpp,实现单链表的各种基本运算和整体建表算法(假设单

链表的元素类型 ElemType为char)在此基础上设计一个程序exp2-2.cpp完成以下功能:

(1)初始化单链表h。

(2)依次采用尾插法插入元素a,b.c、d、e。

(3)输出单链表h。

(4)输出单链表h的长度。

(5)判断单链表h是否为空。

(6)输出单链表的第3个元素。

(7)输出元素a的位置。

(8)在第4个元素的位置上插入元素l。

(9)输出单链表人。

(10)删除单链表h的第3个元素。

(11)输出单链表系h。

(12)释放单链表为h。

Linklist.cpp程序,其中包含如下函数:

· InitList(LinkNode·&.L):初始化单链表L。

· DestroyList(LinkNode·L);释放单链表L。

· ListEmpty(LinkNode·L);判断单链表L.是否为空表。

· ListLength(LinkNode·L.);返同单链表L中的元素个数。

· DispList(LinkNode·L);输出单链表L。

· GetElem(LinkNode ·L.inti.ElemType &-e):获取单链表I中的第;个元素。

· LocateElem(LinkNode·L,ElemTypee);在单链表L中查找元素e。

· ListInsert(LinkNode·&L,inti.ElemTypee);在单链表L的第i个位置上插入元素w。

· ListDelete(LinkNode·8L.inti.ElemType &e):从单链表L.中删除第i个元素

运行代码

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

typedef char ElemType;
typedef struct LNode {
    ElemType data;
    struct LNode* next;
} LinkNode;

// 用头插法建立单链表
void CreateListF(LinkNode*& L, ElemType a[], int n) {
    LinkNode* s;
    L = (LinkNode*)malloc(sizeof(LinkNode));
    L->next = NULL;
    for (int i = 0; i < n; i++) {
        s = (LinkNode*)malloc(sizeof(LinkNode));
        s->data = a[i];
        s->next = L->next;
        L->next = s;
    }
}

// 用尾插法建立单链表
void CreateListR(LinkNode*& L, ElemType a[], int n) {
    LinkNode* s, * r;
    L = (LinkNode*)malloc(sizeof(LinkNode));
    L->next = NULL;
    r = L;
    for (int i = 0; i < n; i++) {
        s = (LinkNode*)malloc(sizeof(LinkNode));
        s->data = a[i];
        r->next = s;
        r = s;
    }
    r->next = NULL;
}

// 初始化线性表
void InitList(LinkNode*& L) {
    L = (LinkNode*)malloc(sizeof(LinkNode));
    L->next = NULL;
}

// 销毁线性表
void DestroyList(LinkNode*& L) {
    LinkNode* pre = L;
    LinkNode* p = pre->next;
    while (p != NULL) {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);
}

// 判断线性表是否为空表
bool ListEmpty(LinkNode* L) {
    return (L->next == NULL);
}

// 求线性表的长度
int ListLength(LinkNode* L) {
    int i = 0;
    LinkNode* p = L;
    while (p->next != NULL) {
        i++;
        p = p->next;
    }
    return i;
}

// 输出线性表
void DispList(LinkNode* L) {
    LinkNode* p = L->next;
    while (p != NULL) {
        printf("%c ", p->data);
        p = p->next;
    }
    printf("\n");
}

// 求线性表中第 i 个元素的值
bool GetElem(LinkNode* L, int i, ElemType& e) {
    int j = 0;
    LinkNode* p = L;
    if (i <= 0) return false;
    while (j < i && p != NULL) {
        j++;
        p = p->next;
    }
    if (p == NULL) return false;
    else {
        e = p->data;
        return true;
    }
}

// 查找第一个值域为 e 的元素的序号
int LocateElem(LinkNode* L, ElemType e) {
    int i = 1;
    LinkNode* p = L->next;
    while (p != NULL && p->data != e) {
        p = p->next;
        i++;
    }
    if (p == NULL) return 0;
    else return i;
}

// 在单链表中第 i 个位置插入元素 e
bool ListInsert(LinkNode*& L, int i, ElemType e) {
    int j = 0;
    LinkNode* p = L;
    if (i <= 0) return false;
    while (j < i - 1 && p != NULL) {
        j++;
        p = p->next;
    }
    if (p == NULL) return false;
    else {
        LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
        s->data = e;
        s->next = p->next;
        p->next = s;
        return true;
    }
}

// 从单链表中删除第 i 个元素
bool ListDelete(LinkNode*& L, int i, ElemType& e) {
    int j = 0;
    LinkNode* p = L;
    LinkNode* q;
    if (i <= 0) return false;
    while (j < i - 1 && p != NULL) {
        j++;
        p = p->next;
    }
    if (p == NULL) return false;
    else {
        q = p->next;
        if (q == NULL) return false;
        e = q->data;
        p->next = q->next;
        free(q);
        return true;
    }
}
excp2-2.cpp
#include <stdio.h>
#include <stdlib.h>
#include "Linklist.cpp"

int main() {
    LinkNode* h;
    ElemType e;
    printf("单链表的基本运算如下:\n");
    printf("(1)初始化单链表 h\n");
    InitList(h);
    printf("(2)依次采用尾插法插入元素 a,b,c,d,e\n");
    ListInsert(h, 1, 'a');
    ListInsert(h, 2, 'b');
    ListInsert(h, 3, 'c');
    ListInsert(h, 4, 'd');
    ListInsert(h, 5, 'e');
    printf("(3)输出单链表 h:");
    DispList(h);
    printf("(4)单链表 h 长度:%d\n", ListLength(h));
    printf("(5)单链表 h 为%s\n", ListEmpty(h) ? "空" : "非空");
    GetElem(h, 3, e);
    printf("(6)单链表 h 的第 3 个元素:%c\n", e);
    printf("(7)元素 a 的位置:%d\n", LocateElem(h, 'a'));
    printf("(8)在第 4 个元素位置上插入元素 f\n");
    ListInsert(h, 4, 'f');
    printf("(9)输出单链表 h:");
    DispList(h);
    printf("(10)删除 h 的第 3 个元素\n");
    ListDelete(h, 3, e);
    printf("(11)输出单链表 h:");
    DispList(h);
    printf("(12)释放单链表 h\n");
    DestroyList(h);
    return 0;
}

代码结果与思路

  1. CreateListF(头插法建立单链表)

    • 首先为单链表创建一个头节点,并将其 next 指针初始化为 NULL
    • 然后遍历给定的字符数组 a,对于数组中的每个元素,创建一个新的节点 s
    • 将新节点 s 的 next 指针指向当前头节点的 next,然后将头节点的 next 指针指向新节点 s,实现头插法插入节点。
  2. CreateListR(尾插法建立单链表)

    • 同样先为单链表创建一个头节点,并将其 next 指针初始化为 NULL。同时定义一个指针 r 指向头节点,用于跟踪单链表的尾节点。
    • 遍历给定的字符数组 a,对于数组中的每个元素,创建一个新的节点 s
    • 将新节点 s 插入到 r 所指节点的后面,然后更新 r 指向新的尾节点。最后将尾节点的 next 指针置为 NULL
  3. InitList(初始化单链表)为单链表分配一个头节点的内存空间,并将头节点的 next 指针初始化为 NULL,表示单链表为空。

  4. DestroyList(销毁单链表)从单链表的头节点开始,遍历单链表,逐个释放每个节点的内存空间。使用两个指针 pre 和 ppre 始终指向当前要释放的节点的前一个节点,p 指向当前要释放的节点。释放完一个节点后,移动指针继续释放下一个节点,直到遍历完整个单链表。

  5. ListEmpty(判断单链表是否为空表)检查单链表的头节点的 next 指针是否为 NULL,如果是,则表示单链表为空,返回 true;否则返回 false

  6. ListLength(求单链表的长度)从单链表的头节点开始遍历单链表,使用一个计数器 i 记录节点的数量。当遍历到单链表的尾节点时,返回计数器的值,即为单链表的长度。

  7. DispList(输出单链表)从单链表的第一个数据节点开始遍历单链表,逐个输出每个节点的 data 域的值,直到遍历到单链表的尾节点。

  8. GetElem(求单链表中第 i 个元素的值)从单链表的头节点开始遍历单链表,使用一个计数器 j 记录当前遍历到的节点位置。当 j 等于 i 时,表示找到了第 i 个节点,将其 data 域的值赋给传入的引用参数 e,并返回 true;如果遍历完单链表还未找到第 i 个节点,则返回 false

  9. LocateElem(查找第一个值域为 e 的元素的序号)从单链表的第一个数据节点开始遍历单链表,逐个比较每个节点的 data 域与给定的元素 e。如果找到相等的节点,则返回该节点的序号(从 1 开始计数);如果遍历完单链表都未找到,则返回 0。

  10. ListInsert(在单链表中第 i 个位置插入元素 e

  • 从单链表的头节点开始遍历单链表,找到第 i - 1 个节点。如果找不到或者 i 不合法,则返回 false
  • 如果找到了第 i - 1 个节点,创建一个新的节点 s,将其 data 域赋值为 e,并将其 next 指针指向第 i 个节点,然后将第 i - 1 个节点的 next 指针指向新节点 s,实现插入操作。

11.ListDelete(从单链表中删除第 i 个元素)

  • 从单链表的头节点开始遍历单链表,找到第 i - 1 个节点。如果找不到或者 i 不合法,则返回 false
  • 如果找到了第 i - 1 个节点,将其下一个节点 q 保存下来。如果 q 为 NULL,表示不存在第 i 个节点,返回 false
  • 如果 q 不为 NULL,将 q 节点的 data 域的值赋给传入的引用参数 e,然后将第 i - 1 个节点的 next 指针指向 q 的下一个节点,释放 q 节点的内存空间,实现删除操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值