数据结构 实验报告(一)

一、实验目的

1、 领会单链表存储结构和掌握单链表中的各种基本运算算法设计;
2、 领会栈链存储结构和掌握栈链中的各种基本运算算法设计;
3、 领会环形队列存储结构和掌握环形队列中的各种基本运算算法设计;
4、 深入掌握单链表应用的算法设计;
5、 掌握栈应用的算法设计;

二、使用仪器、器材

微机一台
操作系统:WinXP
编程软件:C/C++编程软件

三、实验内容及原理

(可能有错误之处,仅供参考~)

1、教材P74

实验题2:实现单链表的各种基本运算的算法
编写一个程序linklist.cpp,实现单链表中的各种基本运算和整体建表算法(假设单链表的元素类型ElemType为char),并在此基础上设计一个程序exp2-2.cpp完成以下功能。
(1)初始化单链表h。
(2)依次采用尾插法插入a、b、c、d、e元素。
(3)输出单链表h。
(4)输出单链表h的长度。
(5)判断单链表h是否为空。
(6)输出单链表h的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素位置上插入f元素。
(9)输出单链表h。
(10)删除单链表h的第3个元素。
(11)输出单链表h。
(12)释放单链表h。

#include <iostream>
using namespace std;

#define ElemType char

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
} *LinkList;

// 初始化
void InitList(LinkList &L)
{
    L = new LNode;
    L->next = NULL;
}

// 打印链表
void PrintList(LinkList &L)
{
    LNode *p = L->next;
    while (p)
    {
        cout << p->data << " ";
        p = p->next;
    }
    cout << "\n";
}

// 输出指定位置的元素
bool PrintList_index(LinkList &L, int n, ElemType &e)
{
    LNode *p = L;
    for (int i = 1; i <= n; i++)
    {
        if (p->next)
            p = p->next;
        else
            return false;
    }
    e = p->data;
    return true;
}

// 尾插法(1)
void CreatList_R(LinkList &L, int n)
{
    LNode *R = L; // 尾指针
    for (int i = 1; i <= n; i++)
    {
        LNode *p = new LNode;
        cin >> p->data;
        p->next = NULL;
        R->next = p;
        R = R->next; // 尾指针后移
    }
}

// 尾插法(2)
void CreatList_R(LinkList &L, int n, ElemType e[])
{
    LNode *R = L;
    for (int i = 0; i < n; i++)
    {
        LNode *p = new LNode;
        p->data = e[i];
        p->next = NULL;
        R->next = p;
        R = R->next; // 尾指针后移
    }
}

// 删除指定位置的元素
bool DeleteList(LinkList &L, int n)
{
    LNode *p = L;
    for (int i = 1; i < n; i++)
    {
        if (p->next)
            p = p->next;
        else
            return false;
    }
    LNode *tmp = p->next;
    if (tmp)
    {
        p->next = p->next->next;
        delete tmp;
        return true;
    }
    return false;
}

// 插入指定位置的元素
bool InsertList(LinkList &L, int n, ElemType e)
{
    LNode *p = L;
    for (int i = 1; i < n; i++)
    {
        if (p->next)
            p = p->next;
        else
            return false;
    }
    LNode *tmp = new LNode;
    tmp->data = e;
    tmp->next = p->next;
    p->next = tmp;
    return true;
}

// 链表长度
int LenList(LinkList &L)
{
    int len = 0;
    LNode *p = L->next;
    while (p)
    {
        len++;
        p = p->next;
    }
    return len;
}

// 链表是否为空
bool EmptyList(LinkList &L)
{
    if (L->next)
        return false;
    else
        return true;
}

// 查找指定位置的元素
bool SearchList(LinkList &L, ElemType e, int &idx)
{
    LNode *p = L->next;
    idx = 1;
    while (p && p->data != e)
    {
        p = p->next;
        idx++;
    }
    return p ? true : false;
}

// 销毁链表
bool DestroyList(LinkList &L)
{
    LNode *p = L;
    while (p)
    {
        LNode *tmp = p;
        p = p->next;
        delete tmp;
        tmp = nullptr;
    }
    L = nullptr;
    return true;
}

int main()
{
    LinkList h;

    printf("(1)初始化单链表h\n");
    InitList(h);

    printf("(2)依次采用尾插法插入a、b、c、d、e元素\n");
    char input[] = "abcde";
    CreatList_R(h, 5, input);

    printf("(3)输出单链表h: ");
    PrintList(h);

    printf("(4)输出单链表h的长度: ");
    printf("%d\n", LenList(h));

    printf("(5)判断单链表h是否为空: ");
    if (EmptyList(h))
        printf("空!\n");
    else
        printf("不空!\n");

    printf("(6)输出单链表h的第3个元素: ");
    char c;
    if (PrintList_index(h, 3, c))
        printf("%c\n", c);
    else
        printf("不存在!\n");

    printf("(7)输出元素a的位置: ");
    int idx;
    if (SearchList(h, 'a', idx))
        printf("%d\n", idx);
    else
        printf("不存在!\n");

    printf("(8)在第4个元素位置上插入f元素: ");
    if (InsertList(h, 4, 'f'))
        printf("插入成功!\n");
    else
        printf("插入失败!\n");

    printf("(9)输出单链表h: ");
    PrintList(h);

    printf("(10)删除单链表h的第3个元素: ");
    if (DeleteList(h, 3))
        printf("删除成功!\n");
    else
        printf("删除失败!\n");

    printf("(11)输出单链表h: ");
    PrintList(h);

    printf("(12)释放单链表h\n");
    DestroyList(h);

    return 0;
}

2、教材P118

实验题2:实现链栈的各种基本运算的算法
编写一个程序linkstack.cpp,实现链栈(假设栈中元素类型ElemType为char)的各种基本运算,并在此基础上设计一个程序exp3-2.cpp完成以下功能。
(1)初始化栈s。
(2)判断栈s是否为空。
(3)依次进栈元素a、b、c、d、e。
(4)判断栈s是否非空。
(5)输出出栈序列。
(6)判断栈s是否非空。
(7)释放栈。

#include <iostream>
#include <string>
using namespace std;

#define MAXSIZE 200
#define ElemType char
//
typedef struct StackNode
{
    ElemType data;
    struct StackNode *next;
} *LinkStack;

void InitStack(LinkStack &S)
{
    // 构造一个空栈,栈顶指针置为空
    S = nullptr;
}

bool StackEmpty(LinkStack S)
{
    // 若栈为空,返回true;否则返回false
    return S == nullptr;
}

// 销毁链栈
bool DestroyStack(LinkStack &S)
{
    StackNode *p = S;
    while (p)
    {
        S = S->next;
        delete p;
        p = S;
    }
    return true;
}

bool PushStack(LinkStack &S, char e)
{
    StackNode *p = new StackNode;

    if (!p)
        return false;

    p->data = e;
    p->next = S;
    S = p;
}

bool PopStack(LinkStack &S, char &e)
{
    if (S == nullptr) // 栈空
        return false;
    e = S->data;
    StackNode *p = S;
    S = S->next;
    delete p;
    return true;
}

bool GetTop(LinkStack &S, char &e)
{
    if (S == nullptr)
        return false; // 栈空
    e = S->data;
    return true;
}

int main()
{
    LinkStack S;

    printf("(1)初始化栈s\n");
    InitStack(S); // 初始化栈

    printf("(2)判断栈s是否为空: %s\n", StackEmpty(S) ? "空!" : "不空!");

    printf("(3)依次进栈元素: a b c d e\n");
    char input[] = "abcde";
    for (int i = 0; i < 5; i++)
        PushStack(S, input[i]);

    printf("(4)判断栈s是否为空: %s\n", StackEmpty(S) ? "空!" : "不空!");

    printf("(5)输出出栈序列: ");
    char output;
    while (PopStack(S, output))
    {
        printf("%c ", output);
    }

    printf("\n(6)判断栈s是否为空: %s\n", StackEmpty(S) ? "空!" : "不空!");

    printf("(7)释放栈\n");
    DestroyStack(S); // 释放栈

    return 0;
}

3、教材P118

实验题3:实现环形队列的各种基本运算的算法
编写一个程序sqqueue.cpp,实现环形队列(假设队列中元素类型ElemType为char)的各种基本运算,并在此基础上设计一个程序exp3-3.cpp完成以下功能。
(1)初始化队列q。
(2)判断队列q是否非空。
(3)依次进队元素a、b、c。
(4)出队一个元素,输出该元素。
(5)依次进队元素d、e、f。
(6)输出出队序列。
(12)释放队列。

#include <iostream>
#include <cstring>
#define ElemType char
using namespace std;

#define MAXSIZE 100

typedef struct
{
    ElemType *base;
    int front;
    int rear;
} Queue;

// 初始化
bool InitQueue(Queue &Q)
{
    Q.base = new ElemType[MAXSIZE];
    if (!Q.base)
        return false;
    Q.front = Q.rear = 0;
    return true;
}

bool EmptyQueue(Queue &Q)
{
    return Q.front == Q.rear;
}

// 插入
bool EnQueue(Queue &Q, ElemType &e)
{
    if((Q.rear + 1) % MAXSIZE == Q.front)
        return false;
    Q.base[Q.rear] = e;
    Q.rear = (Q.rear + 1) % MAXSIZE;
    return true;
}

// 删除
bool DlQueue(Queue &Q, ElemType &e)
{
    if(EmptyQueue(Q))
        return false;
    e = Q.base[Q.front];
    Q.front = (Q.front + 1) % MAXSIZE;
    return true;
}

bool DestroyQueue(Queue &Q)
{
    delete[] Q.base;
    Q.front = Q.rear = 0;
    Q.base = nullptr;
    return true;
}

int main()
{
    Queue Q;
    printf("(1)初始化队列q\n");
    InitQueue(Q);

    printf("(2)判断队列q是否非空: %s\n", EmptyQueue(Q) ? "空!" : "不空!");

    printf("(3)依次进队元素a b c\n");
    char input[] = "abc";
    for(int i = 0; i < 3; i++)
        EnQueue(Q,input[i]);
    
    char output;
    DlQueue(Q,output);
    printf("(4)出队一个元素,输出该元素: %c\n", output);

    printf("(5)依次进队元素d e f\n");
    strcpy(input,"def");
    for(int i = 0; i < 3; i++)
        EnQueue(Q,input[i]);

    printf("(6)输出出队序列: ");
    while(DlQueue(Q,output))
        printf("%c ", output);
    
    printf("\n(7)释放队列\n");
    DestroyQueue(Q);

    return 0;
}

4、教材P77

实验题12:用单链表实现两个大整数的相加运算
编写一个程序exp2-12.cpp完成以下功能。
(1)将用户输入的十进制整数字符串转化为带头结点的单链表,每个结点存放一个整数位。
(2)求两个整数单链表相加的结果单链表。
(3)求结果单链表的中间位,如123的中间位为2,1234的中间位为2。

#include <iostream>
using namespace std;

#define ElemType int

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
} *LinkList;

// 初始化
void InitList(LinkList &L)
{
    L = new LNode;
    L->next = NULL;
}

// 打印链表【返回链表长度】
int PrintList(LinkList &L)
{
    int num = 0;
    LNode *p = L->next;
    while (p)
    {
        num++;
        cout << p->data;
        p = p->next;
    }
    cout << "\n";
    return num;
}

// 输出指定位置的元素
bool PrintList_index(LinkList &L, int n, ElemType &e)
{
    LNode *p = L;
    for (int i = 1; i <= n; i++)
    {
        if (p->next)
            p = p->next;
        else
            return false;
    }
    e = p->data;
    return true;
}

// 尾插法(1)
void CreatList_R(LinkList &L, int n)
{
    LNode *R = L; // 尾指针
    for (int i = 1; i <= n; i++)
    {
        LNode *p = new LNode;
        cin >> p->data;
        p->next = NULL;
        R->next = p;
        R = R->next; // 尾指针后移
    }
}

// 尾插法(2)
// 注意:数字从低位开始保存:如1234 链表中保存为 4->3->2->1
void CreatList_R(LinkList &L, string num)
{
    LNode *R = L;
    for (int i = num.size() - 1; i >= 0; i--)
    {
        LNode *p = new LNode;
        p->data = num[i] - '0';
        p->next = NULL;
        R->next = p;
        R = R->next; // 尾指针后移
    }
}

// 删除指定位置的元素
bool DeleteList(LinkList &L, int n)
{
    LNode *p = L;
    for (int i = 1; i < n; i++)
    {
        if (p->next)
            p = p->next;
        else
            return false;
    }
    LNode *tmp = p->next;
    if (tmp)
    {
        p->next = p->next->next;
        delete tmp;
        return true;
    }
    return false;
}

// 插入指定位置的元素
bool InsertList(LinkList &L, int n, ElemType e)
{
    LNode *p = L;
    for (int i = 1; i < n; i++)
    {
        if (p->next)
            p = p->next;
        else
            return false;
    }
    LNode *tmp = new LNode;
    tmp->data = e;
    tmp->next = p->next;
    p->next = tmp;
    return true;
}

// 链表长度
int LenList(LinkList &L)
{
    int len = 0;
    LNode *p = L->next;
    while (p)
    {
        len++;
        p = p->next;
    }
    return len;
}

// 链表是否为空
bool EmptyList(LinkList &L)
{
    if (L->next)
        return false;
    else
        return true;
}

// 查找指定位置的元素
bool SearchList(LinkList &L, ElemType e, int &idx)
{
    LNode *p = L->next;
    idx = 1;
    while (p && p->data != e)
    {
        p = p->next;
        idx++;
    }
    return p ? true : false;
}

// 销毁链表
bool DestroyList(LinkList &L)
{
    LNode *p = L;
    while (p)
    {
        LNode *tmp = p;
        p = p->next;
        delete tmp;
        tmp = nullptr;
    }
    L = nullptr;
    return true;
}

// 反转链表
void Reverse_List(LinkList &L)
{
    //从首元结点开始处理
    LNode *prev = L->next; // 指向前一个结点
    LNode *curr = L->next->next; // 指向当前结点
    while(curr)
    {
        LNode *tmp = curr->next; // 临时保存【下一个结点】
        curr->next = prev;
        //指针后移,注意两条语句的顺序
        prev = curr;
        curr = tmp;
    }
    //最后,先把首元结点的next指向空
    L->next->next = NULL;
    //再把头结点指向原本的最后一个元素【prev】
    L->next = prev;
}

LinkList Add(LinkList &A, LinkList &B)
{
    LinkList C;
    InitList(C);

    int t = 0; // 保存进位

    LNode *a = A->next;
    LNode *b = B->next;
    LNode *c = C;

    while(a || b || t)
    {
        LNode *p = new LNode;
        p->next = NULL;

        if(a) t += a->data, a = a->next;
        if(b) t += b->data, b = b->next;

        p->data = t % 10; // 保存当前位
        t /= 10; // 计算进位
        
        c->next = p;
        // 指针后移
        c = c->next;
    }

    return C;
}

int main()
{
    LinkList a, b;
    InitList(a);
    InitList(b);
    string A, B;

    printf("请输入两个整数: \n");
    cin >> A >> B;

    CreatList_R(a, A);
    CreatList_R(b, B);

    // 保存结果
    LinkList c = Add(a, b);
    // 保存结果的链表C反转
    Reverse_List(c);

    // 结果单链表的中间位保存到 e 中
    int e;
    printf("\n两个数相加后结果为:\n");
    PrintList_index(c, (PrintList(c) + 1) / 2, e);
    printf("\n结果单链表的中间位为: \n%d\n", e);

    return 0;
}

5、教材P119

实验题7:求解栈元素排序问题
编写一个程序exp3-7.cpp,按升序对一个字符栈进行排序,即最小元素位于栈顶,最多只能使用一个额外的栈存放临时数据,并输出栈排序过程。

#include <iostream>
#include <string>
using namespace std;
#define MAXSIZE 200

// 顺序栈
typedef struct
{
    char *base;    // 栈底指针
    char *top;     // 栈顶指针
    int stacksize; // 栈可用最大容量
} SqStack;

bool InitStack(SqStack &S)
{
    // 构造一个空栈
    S.base = new char[MAXSIZE];
    if (!S.base)
        return false; // 存储分配失败
    S.top = S.base;   // 栈顶指针等于栈底指针
    S.stacksize = MAXSIZE;
    return true;
}

bool StackEmpty(SqStack S)
{
    // 若栈为空,返回TRUE;否则返回FALSE
    if (S.top == S.base)
        return true;
    else
        return false;
}

int StackLength(SqStack S)
{
    // 指针相减,结果为元素个数
    return S.top - S.base;
}

// 清空顺序栈[不是销毁]
bool ClearStack(SqStack &S)
{
    if (S.base)
        S.top = S.base;
    return true;
}

// 销毁顺序栈
bool DestroyStack(SqStack &S)
{
    if (S.base)
    {
        delete []S.base;
        S.stacksize = 0;
        S.base = S.top = nullptr;
    }
    return true;
}

bool PushStack(SqStack &S, char e)
{
    if (S.top - S.base == S.stacksize) // 栈满
        return false;
    *S.top++ = e; // 相当于*S.top=e;  S.top++;
    return true;
}

bool PopStack(SqStack &S, char &e)
{
    // 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
    if (S.top == S.base) // 栈空
        return false;
    e = *--S.top; // 相当于--S.top;   e=*S.top;
    return true;
}

bool GetTop(SqStack S, char &e)
{
    if (S.top == S.base)
        return false; // 栈空
    e = *(S.top - 1);
    return true;
}

void Solve(SqStack &S)
{
    int num = 1;
    // 开辟一个额外的栈
    printf("(%d) 开辟一个额外的栈tmp\n", num++);
    SqStack tmp;
    InitStack(tmp);

    while (!StackEmpty(S))
    {
        // 先取出S的栈顶e
        char e;
        PopStack(S, e);
        printf("(%d) 取出S的栈顶: %c\n", num++, e);
        // 情况1:tmp不空
        while (!StackEmpty((tmp)))
        {
            // 获取tmp 的栈顶
            char t;
            GetTop(tmp, t);
            printf("(%d) 当前栈tmp不空, 获取栈tmp 的栈顶: %c\n", num++, t);
            // 如果 S栈顶 >= tmp栈顶
            if (e >= t)
            {
                // 那么直接把它加入tmp即可
                PushStack(tmp, e);
                printf("(%d) 因为【原来的S栈顶 %c >= 当前tmp栈顶 %c】, 所以把原来的S栈顶 %c 加入tmp \n", num++, e, t, e);
                break;
            }
            // 如果 S栈顶 < tmp栈顶
            else
            {
                // 不断取出tmp栈顶,放入S中(注意:最初的S栈顶e已被取出),直至e可以放入到tmp中
                // 最后使得tmp【一直】呈【降序】排序
                printf("(%d) 因为【原来的S栈顶 %c < 当前tmp栈顶 %c】, 所以取出当前的tmp栈顶 %c 加入栈S中 \n", num++, e, t, t);
                PopStack(tmp, t);
                PushStack(S, t);
            }
        }

        // 情况2:tmp空
        if (StackEmpty(tmp))
        {
            printf("(%d) 当前栈tmp空, 把栈S的栈顶元素 %c 取出并加入到栈tmp中\n", num++, e);
            PushStack(tmp, e); // 直接把S的栈顶元素e放到tmp即可
        }

    }

    // 以上算法结束后,tmp内元素呈【降序】排序,重新将其放入到S中,即可使得S内的元素呈【升序】排序
    printf("(%d) 最后, 重新把栈tmp中的元素放入栈S中: ", num++);
    while (!StackEmpty(tmp))
    {
        char t;
        PopStack(tmp, t);
        PushStack(S, t);
        printf("%c ", t);
    }
    printf("\n");
    // 销毁tmp
    DestroyStack(tmp);
}

int main()
{
    SqStack S;
    if (InitStack(S))
    {
        int N;
        printf("请问需要存放几个元素?\n");
        scanf("%d", &N);
        printf("请输入元素: \n");
        for (int i = 0; i < N; i++)
        {
            char t;
            cin >> t;
            if (!PushStack(S, t))
            {
                printf("空间不足,插入失败!\n");
                return 0;
            }
        }
        printf("\n排序过程: \n");
        Solve(S);
        printf("\n排序后结果为:");
        while (!StackEmpty(S))
        {
            char c;
            PopStack(S, c);
            printf("%c ", c);
        }
        printf("\n");
    }
    
return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值