《数据结构》课后作业

  这是一篇记录《数据结构》课程课后作业的博客,我所使用的教科书是严蔚敏主编的C语言版数据结构,但是由于习惯所致,本篇博客会尽量在和书本风格同步的情况下使用C++编写程序,本文中的程序都是李岚老师上课布置的题目的个人解析,如有漏洞,欢迎指出!

绪论部分

  1.写一个复数抽象类型定义,实现加乘运算

    显然对于该问题,只需明确复数的组成包括实部和虚部,再了解复数加法和乘法的运算规则即可求解:

    设z1 = a+bi,z2 = c+di(a、b、c、d∈R)是任意两个复数,那么

       它们的和是 z1+z2 = (a+c)+(b+d)i,它们的积是z1+z2 = (ac-bd)+(bc+ad)i

    编写程序如下:

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

typedef struct Node
{
    int a;   //实部;
    int b;  //虚部;
}Complex;

Complex Add(Complex x,Complex y)
{
    Complex res;
    res.a = x.a+y.a;
    res.b = x.b+y.b;
    return res;
}

Complex Multipy(Complex x,Complex y)
{
    Complex res;
    res.a = x.a*y.a-x.b*y.b;
    res.b = x.b*y.a+x.a*y.b;
    return res;
}

int main()
{
    Complex a,b,c;
    cout<<"Enter a and b, represent Complex A = a+bi"<<endl;
    cin>>a.a>>a.b;
    cout<<"Enter c and d, represent Complex B = c+di"<<endl;
    cin>>b.a>>b.b;
    c = Add(a,b);
    printf("A+B = %d%+di\n",c.a,c.b);
    c = Multipy(a,b);
    printf("A*B = %d%+di\n",c.a,c.b);
    return 0;
}

  2.用流程图表示一元二次函数的求解过程

线性表部分

  1.在逻辑层面求两集合的差集

    显然对于该问题,由定义设集合A,B,则A与B的差集为:A-B && B-A,根据对称差运算的性质,即可编写程序如下:

#include<cstdio>
#include<iostream>
#define inf -1000000000
using namespace std;

int main()
{
    int A[1000],B[1000],m,n;
    cout<<"Enter m,n,indicating set A contains m elements,set B contains n elements"<<endl;
    cin>>m>>n;
    cout<<"Enter "<<m<<" different elems: "<<endl;
    for(int i = 0; i < m; i++)
        cin>>A[i];
    cout<<"Enter "<<n<<" different elems: "<<endl;
    for(int i = 0; i < n; i++)
        cin>>B[i];
    for(int i = 0; i < m; i++)
        for(int j = 0; j < n; j++)
            if(A[i] == B[j])
            {
                A[i] = B[j] = inf;
                break;                //A或B中不该出现重复元素,所以找到直接break;
            }
    cout<<"A-B: "<<endl;
    for(int i = 0; i < m; i++)
        if(A[i] != inf)
            cout<<A[i]<<" ";
    cout<<endl;
    cout<<"B-A: "<<endl;
    for(int i = 0; i < n; i++)
        if(B[i] != inf)
            cout<<B[i]<<" ";
    cout<<endl;
    return 0;
}

  2.在顺序表A的第i个元素前插入元素B

    顺序表,不用多说,先建立表A,再定位插入位置,最后插入即可

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define INIT_SIZE 100
#define DLC 10
#include<cstdlib>
#include<iostream>
using namespace std;
typedef int Status,ElemType;

typedef struct
{
    ElemType *elem;
    int length,listsize;
}SqList;

Status initSqlist(SqList &L)
{
    L.elem = (ElemType *)malloc(INIT_SIZE*sizeof(ElemType));
    if(!L.elem) exit(OVERFLOW);
    L.length = 0;
    L.listsize = INIT_SIZE;
    return OK;
}

Status insertElem(SqList &L,int i,ElemType e)
{
    if(i < 1 || i > L.length+1)   return ERROR;
    if(L.length >= L.listsize)
    {
        ElemType *newbase = (ElemType *)realloc(L.elem,(L.listsize+DLC)*sizeof(ElemType));
        if(!newbase)    exit(OVERFLOW);
        L.elem = newbase;
        L.listsize += DLC;
    }
    for(int j = L.length; j >= i; j--)
        L.elem[j] = L.elem[j-1];
    L.elem[i-1] = e;
    L.length++;
    return OK;
}

int main()
{
    int n,m,pos;
    ElemType t;
    SqList L;
    initSqlist(L);
    cout<<"Enter n,m:"<<endl;
    cin>>n>>m;
    cout<<"Enter n elems to form SqList A:"<<endl;
    for(int i = 1; i <= n; i++)
    {
        cin>>t;
        insertElem(L,i,t);
    }
    cout<<"Enter m elems to insert(pos,elem):"<<endl;
    for(int i = 0; i < m; i++)
    {
        cin>>pos>>t;
        insertElem(L,pos,t);
    }
    cout<<"Result:"<<endl;
    for(int i = 0; i < L.length; i++)
        cout<<L.elem[i]<<" ";
    cout<<endl;
    return 0;
}

  3.  在顺序表A的第i个元素前插入表B

    这里可以把B当成一个区间,插入到A,应该先判断是否应该对A进行扩容,然后A中相应元素移位,最后代码如下:

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define INIT_SIZE 100
#define DLC 10
#include<iostream>
#include<cstdlib>
using namespace std;

typedef int Status,ElemType;

typedef struct Node
{
    ElemType *elem;
    int length,listsize;
}SqList;

Status initSqList(SqList &L)
{
    L.elem = (ElemType *)malloc(INIT_SIZE*sizeof(ElemType));
    if(!L.elem) exit(OVERFLOW);
    L.length = 0;
    L.listsize = INIT_SIZE;
    return OK;
}

Status insertElem(SqList &L,int i,ElemType e)   //单点插入;
{
    if(i < 1 || i > L.length+1) return ERROR;
    if(L.length >= L.listsize)
    {
        ElemType *tmp;
        tmp = (ElemType *)realloc(L.elem,(DLC+L.listsize)*sizeof(ElemType));
        if(!tmp)    exit(OVERFLOW);
        L.elem = tmp;
        L.listsize += DLC;
    }
    for(int j = L.length; j >= i; j--)
        L.elem[j] = L.elem[j-1];
    L.elem[i-1] = e;
    L.length++;
    return OK;
}

Status insertList(SqList &L,int i,SqList T) //区间插入;
{
    if(i < 1 || i > L.length) return ERROR;
    if(L.length+T.length >= L.listsize)
    {
        ElemType *tmp;
        tmp = (ElemType *)realloc(L.elem,(T.length+L.listsize+DLC)*sizeof(ElemType));
        if(!tmp)    exit(OVERFLOW);
        L.elem = tmp;
        L.listsize += T.length+DLC;
    }
    for(int j = L.length+T.length-1; j >= i-1+T.length; j--)
        L.elem[j] = L.elem[j-T.length];
    for(int j = i-1; j < T.length+i-1; j++)
        L.elem[j] = T.elem[j-i+1];
    L.length += T.length;
    return OK;
}

void output(SqList L)
{
    for(int i = 0; i < L.length; i++)
        cout<<L.elem[i]<<" ";
    cout<<endl;
}

int main()
{
    int pos,m,n;
    SqList L,T;
    ElemType e;
    initSqList(L);
    initSqList(T);
    cout<<"Enter m,n, indicating SqList A contains m elems, B contains n elems:"<<endl;
    cin>>m>>n;
    cout<<"Enter "<<m<<" elems for A:"<<endl;
    for(int i = 1; i <= m; i++)
    {
        cin>>e;
        insertElem(L,i,e);
    }
    cout<<"Enter "<<n<<" elems for B:"<<endl;
    for(int i = 1; i <= n; i++)
    {
        cin>>e;
        insertElem(T,i,e);
    }
    cout<<"Enter a position, at where you want B in A:"<<endl;
    cin>>pos;
    cout<<"Results:"<<endl;
    if(insertList(L,pos,T))
        output(L);
    else cout<<"ERROR!"<<endl;
    return 0;
}

  4.对于顺序表A,删除从位置i起的连续k个元素

    这个,也是非常简单的一个模拟,只需要找到第i个元素,将之后所有元素向前移动k位即可,注意最后顺序表长度的修改!

    代码如下:

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define INIT_SIZE 100
#define DLC 10
#include<iostream>
#include<cstdlib>
using namespace std;

typedef int Status,ElemType;

typedef struct Node
{
    ElemType *elem;
    int length,listsize;
}SqList;

Status initSqList(SqList &L)
{
    L.elem = (ElemType *)malloc(INIT_SIZE*sizeof(ElemType));
    if(!L.elem) exit(OVERFLOW);
    L.length = 0;
    L.listsize = INIT_SIZE;
    return OK;
}

Status insertElem(SqList &L,int i,ElemType e)   //单点插入;
{
    if(i < 1 || i > L.length+1) return ERROR;
    if(L.length >= L.listsize)
    {
        ElemType *tmp;
        tmp = (ElemType *)realloc(L.elem,(DLC+L.listsize)*sizeof(ElemType));
        if(!tmp)    exit(OVERFLOW);
        L.elem = tmp;
        L.listsize += DLC;
    }
    for(int j = L.length; j >= i; j++)
        L.elem[j] = L.elem[j-1];
    L.elem[i-1] = e;
    L.length++;
    return OK;
}

Status deleteRange(SqList &L,int i,int k) //区间删除;
{
    if(i < 1 || i+k > L.length+1) return ERROR;
    for(int j = i-1; j < L.length; j++)
        L.elem[j] = L.elem[j+k];
    L.length -= k;
    return OK;
}

void output(SqList L)
{
    for(int i = 0; i < L.length; i++)
        cout<<L.elem[i]<<" ";
    cout<<endl;
}

int main()
{
    int pos,n,range;
    SqList L;
    ElemType e;
    initSqList(L);
    cout<<"Enter n, indicating SqList A contains n elems:"<<endl;
    cin>>n;
    cout<<"Enter "<<n<<" elems:"<<endl;
    for(int i = 1; i <= n; i++)
    {
        cin>>e;
        insertElem(L,i,e);
    }
    cout<<"Enter i,k, to delete range[i,i+k):"<<endl;
    cin>>pos>>range;
    cout<<"Results:"<<endl;
    if(deleteRange(L,pos,range))
        output(L);
    else cout<<"ERROR!"<<endl;
    return 0;
}

  5.统计单链表中值为x的元素个数

    这个题目,呃,就是把遍历函数改一下加个计数器就好了,代码如下:

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#include<iostream>
#include<cstdlib>
using namespace std;
typedef int Status,ElemType;

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

Status creatLinkList(LinkList &L)
{
    int n;
    L = (LinkList)malloc(sizeof(LNode));
    if(!L)    exit(OVERFLOW);
    L->data = 0;
    LinkList Tail = L;       //尾指针;
    Tail->next = nullptr;
    cout<<"Enter n:"<<endl;
    cin>>n;
    cout<<"Enter "<<n<<" elems to insert:"<<endl;
    while(n--)
    {
        LinkList tmp = (LinkList)malloc(sizeof(LNode));
        if(!tmp)    exit(OVERFLOW);
        cin>>tmp->data;
        Tail->next = tmp;
        Tail = tmp;
        tmp = nullptr;
        L->data++;
    }
    Tail->next = nullptr;
    return OK;
}

int countX(LinkList L,ElemType x)    //计数;
{
    int cnt = 0;
    L = L->next;
    while(L)
    {
        if(L->data == x)    cnt++;
        L = L->next;
    }
    return cnt;
}

int main()
{
    ElemType x;
    LinkList L;
    creatLinkList(L);
    cout<<"Enter x:"<<endl;
    cin>>x;
    cout<<"The number of "<<x<<" in LinkList:"<<endl;
    cout<<countX(L,x)<<endl;
    return 0;
}

  6.删除单链表中相同元素

    这个题目,可以嵌套循环,第一层循环遍历链表,在第i个节点记录T->data,内层循环从i+1一直到表尾,用j作计数器,当找到和T->data相等的元素时,就删除第i+j个节点,反复如此直到循环结束即可,代码如下:

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#include<iostream>
#include<cstdlib>
using namespace std;
typedef int Status,ElemType;

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

Status creatLinkList(LinkList &L)
{
    int n;
    L = (LinkList)malloc(sizeof(LNode));
    if(!L)    exit(OVERFLOW);
    L->data = 0;
    LinkList Tail = L;       //尾指针;
    Tail->next = nullptr;
    cout<<"Enter n:"<<endl;
    cin>>n;
    cout<<"Enter "<<n<<" elems to insert:"<<endl;
    while(n--)
    {
        LinkList tmp = (LinkList)malloc(sizeof(LNode));
        if(!tmp)    exit(OVERFLOW);
        cin>>tmp->data;
        Tail->next = tmp;
        Tail = tmp;
        tmp = nullptr;
        L->data++;
    }
    Tail->next = nullptr;
    return OK;
}

Status deleteElem(LinkList L,int i,ElemType &e) //单点删除;
{
    if(i < 1 || i > L->data)   return ERROR;
    L->data--;
    while(i > 1)
    {
        i--;
        L = L->next;
    }
    LinkList tmp = L->next;
    e = tmp->data;
    L->next = tmp->next;
    free(tmp);
    return OK;
}

Status deleteSameElems(LinkList L)  //重复元素删除;
{
    int i = 1;
    ElemType e;
    LinkList p = L->next;
    while(p)
    {
        int j = 1;
        ElemType tmp = p->data;
        LinkList t = p->next;
        while(t)
        {
            if(t->data == tmp)
            {
                deleteElem(L,i+j,e);
                cout<<e<<" has been deleted!"<<endl;
            }
            else j++;
            t = t->next;
        }
        p = p->next;
        i++;
    }
    return OK;
}

void Traverse(LinkList L)
{
    L = L->next;
    while(L)
    {
        cout<<L->data<<" ";
        L = L->next;
    }
    cout<<endl;
}

int main()
{
    ElemType e;
    LinkList L;
    creatLinkList(L);
    deleteSameElems(L);
    cout<<"Remaining LinkList:"<<endl;
    Traverse(L);
    return 0;
}

  PS: 讲点题外话,今天上课学了一个有点意思的算法:单链表的转置,实际上是使用三个指针不断移动达到转置的效果,算法时间复杂度很优秀,为O(n),空间复杂度为O(1),实现如下:

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#include<iostream>
#include<cstdlib>
using namespace std;
typedef int Status,ElemType;

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

Status creatLinkList(LinkList &L)
{
    int n;
    ElemType e;
    L = (LinkList)malloc(sizeof(LNode));
    if(!L)    exit(OVERFLOW);
    L->data = 0;
    LinkList Tail = L;       //尾指针;
    Tail->next = nullptr;
    cout<<"Enter n:"<<endl;
    cin>>n;
    cout<<"Enter "<<n<<" elems to insert:"<<endl;
    while(n--)
    {
        LinkList tmp = (LinkList)malloc(sizeof(LNode));
        if(!tmp)    exit(OVERFLOW);
        cin>>tmp->data;
        Tail->next = tmp;
        Tail = tmp;
        tmp = nullptr;
        L->data++;
    }
    Tail->next = nullptr;
    return OK;
}

void reverseLinkList(LinkList &L)
{
    if(L->data < 2) return;
    LinkList p,q,r;
    p = L->next;
    q = p->next;
    r = q->next;
    p->next = nullptr;  //修改表尾;
    while(q->next)
    {
        q->next = p;
        p = q;
        q = r;
        r = r->next;
    }
    q->next = p;    //处理表尾;
    L->next = q;    //修改头指针;
}

void Traverse(LinkList L)
{
    L = L->next;
    while(L)
    {
        cout<<L->data<<" ";
        L = L->next;
    }
    cout<<endl;
}

int main()
{
    ElemType e;
    LinkList L;
    creatLinkList(L);
    cout<<"Before reversing:"<<endl;
    Traverse(L);
    reverseLinkList(L);
    cout<<"After reversing:"<<endl;
    Traverse(L);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/AAMahone/article/details/82430764