DS博客作业2--线性表

0.PTA得分截图

1.本周学习总结

1.1 总结线性表内容

  • 顺序表

1.顺序表结构体定义

#define MaxSize 50        //设置线性表最大长度,方便修改
typedef int ElemType;            //为int类型取别名ElemType
typedef struct
{
    ElemType data[MaxSize];            //定义数组存放线性表元素
    int length;                    //记录线性表长度
}SqList,*List;            //定义顺序表类型

2.顺序表的建立

void CreatList(List &L,ElemType a[],int n)            //由传入的a中的n个元素来建立线性表
{
    int i=0;            
    int k=0;            //k表示L中元素个数,开始顺序表为空,所以K初始值为0

    L=new SqList;            //给顺序表分配空间

    while(i<n)                //利用while循环扫描数组a
    {
    L->data[k]=a[i];            //将数组a中的元素a[i]放入L中
    k++;                
    i++;
    }

    L->length=k;                   //记录顺序表长度为k
}

3.顺序表的元素插入(利用布尔类型来返回插入结果,返回True表示插入成功,返回False表示插入失败)

bool ListInsert(List &L,int i,ELemType e)
{
    int j;
    if(i<1||i>L->lengeh+1)            //若参数i小于1或者大于数组长度+1,则改参数错误,返回False
    {
        return False;
    }

    i--;                                //将插入位置的逻辑序号转换成为对应的物理序号

    for(j=L->length;j>i;j--)            //若该位置存在,则将该位置及其后的所有元素后移一位
    {
        L->data[j]=L->data[j-1];
    }

    L->data[i]=e;                        //将待插入元素e插入
    L->length++;                         //因为插入一个元素,所以顺序表元素多了一个,顺序表长度增1
    return True;                         //插入成功,返回True

4.顺序表元素的删除(利用布尔类型来返回删除结果)

bool ListDelete(List &L, int i, ElemType &e)
{
    int j;
    
    if(i<1||i>L->lengeh+1)            //若参数i小于1或者大于数组长度+1,则改参数错误,返回False
    {
        return False;
    }

    i--;

    e=L->data[i];            
    
    for(j=i;j<L->length;j++)        //利用循环覆盖第i个值
    {
        L->data[j]=L->data[j+1];
    }
    
    L->length--;            //因为成功删除第i个值,元素少了一个,顺序表长度减1
    return True;            //删除成功,返回True
}
  • 链表

1.链表结构体定义

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

2.头插法,尾插法建链表

 //头插法建链表
void CreateListF(LinkList& L, int n)           
{

    L =  new LNode;
    L->next = NULL;
        LinkList p;

    while (n--)
    {
        p =  new LNode;
        cin >> p->data;
        p->next = L->next;
        L->next = p;
    }
}
//尾插法建链表
void CreateListR(LinkList& L, int n)                
{
    L = new LNode;
    LinkList p;
    LinkList ptail = L;                
    ptail->next = NULL;
    while (n--)
    {
        p = new LNode;
        cin >> p->data;
        ptail->next = p;
        ptail = p;
    }
    ptail->next = NULL;
}

3.链表插入

void ListInsert(Linklist& L, int i, ElemType e) 
{  
    LinkList p;
    p = L->next;
    j = 0;

    while (p && j < i - 1) 
    {
        p = p->next;
        j++;
    }

    if (!p || i <= 0) 
    {
        cout << "位置错误!" << endl;
    }
    else
    {
        s = new node();
        s->data = e;
        s->next = p->next;
        p->next = s;
    }
}

4.链表删除

void ListDelete(Linklist& L, int i) 
{  
    LinkList p;
    p = L->next;
    j = 0;

    while (p->next && j < i - 1) 
    {
        p = p->next;
        j++;
    }

    if (!p || i <= 0) 
    {
        cout << "位置错误!" << endl;
    }
    else
    {
        s = new node();
        s = p->next;
        p->next = p->next->next;
        delete s;
    }
}

5.链表分割

void SplitList(LinkList& L, LinkList& L1, LinkList& L2)
{
    LinkList p;
    LinkList prev;
    LinkList ptail;
    L2 = new LNode;
    prev = L->next;
    L1 = L;
    L1->next = NULL;
    L2->next = NULL;
    
    ptail = L1;
    int i;

    for (i = 1; prev; i++, prev = prev->next)
    {
        p = new LNode;
        p->data = prev->data;
        p->next = NULL;

        if (i % 2 == 1)
        {
            ptail->next = p;
            ptail = p;
        }
        else
        {
            p->next = L2->next;
            L2->next = p;
        }

    }
}
  • 有序表(有序单链表)

1.插入

void ListInsert(LinkList& L, ElemType e)
{
    LinkList x = L;                    
    LinkList p = new LNode;            //新开辟p一个节点存储传入的值e
    p->data = e;                       
    while (x->next && x->next->data < e)            //利用while循环来寻找插入位置
    {
        x = x->next;
    }
    p->next = x->next;                    //将存储e的新节点插入找到的位置中
    x->next = p;
}

2.删除

void ListDelete(LinkList& L, ElemType e)
{
    int flag = 1;                        //利用flag来判断成功删除传入数据e,给flag赋初值1
    LinkList x = new LNode;
    LinkList p = L;                

    x->next = NULL;

    if (p->next == NULL)
    {
        return;
    }
    while (p->next)                //利用while循环来寻找待删除元素,一旦找到该待删除元素,终止循环,并将flag的值变为e
    {
        if (p->next->data == e)
        {
            x = p->next;
            p->next = x->next;
            flag = 0;
                        delete x;                        //找到该元素之后链表中删除该元素,并释放该节点
            break;
        }
        p = p->next;
    }
    if (flag == 1)                            //若未找到该元素,则输出"找不到!"
    {
        cout << e << "找不到!" << endl;
    }
}

3.有序表合并

void MergeList(LinkList &L1,LinkList L2)
{
    LinkList p, head;
    head = L1;
    while (L2->next&&head->next)
    {
        if (head->next->data > L2->next->data)
        {
            p = new LNode;
            p->data = L2->next->data;
            p->next = head->next;
            head->next = p;
            L2 = L2->next;
        }
        else if(head->next->data == L2->next->data)
        {
            L2 = L2->next;
        }
        head = head->next;
    }
    if (head->next == NULL)
    {
        head->next = L2->next;
    }
}
  • 双向链表操作

0.主函数

int main()            
{
    LinkList L;
    LinkList Lr;        //存储链表尾结点,方便反向对链表进行操作
    int n;
    cin >> n;
    CreateList(L, n, Lr);
    DispListF(L);
    DispListR(L, Lr);
    DestroyList(L);
    return 0;
}

1.双向链表的结构体定义

typedef int ElemType;
typedef struct node
{
    ElemType data;
    struct node* pre;        //指向前一节点的指针
    struct node* next;       //指向后一节点的指针
}LNode, *LinkList;

2.双向链表建立

void CreateListR(LinkList& L, int n, LinkList& Lr)
{
    L = new LNode;
    L->next = NULL;
    L->pre = NULL;
    LinkList p, ptail;
    ptail = L;
    while (n--)
    {
        p = new LNode;
        cin >> p->data;
        p->next = ptail->next;
        ptail->next = p;
        p->pre = ptail;
        ptail = p;
    }
    Lr = ptail;
}
//正向输出链表
void DispListF(LinkList L)
{
    LinkList p;
    p = L->next;
    if (p != NULL)
    {
        while (p->next)
        {
            cout << p->data << " ";
            p = p->next;
        }
        cout << p->data << endl;
    }
    else
    {
        cout << "空链表!" << endl;
    }
}
//利用主函数中存储的尾结点位置,直接反向输出链表
void DispListR(LinkList L, LinkList Lr)
{
    LinkList p;
    p = Lr;
    while (p->pre->pre)
    {
        cout << p->data << " ";
        p = p->pre;
    }
    cout << p->data << endl;
}

结构特点:有两个指针,一个指向后继节点,一个指向前驱结点

  • 单循环链表

1.结构体定义

typedef int ElemType;
typedef struct node
{
    ELemType data;
    struct node* next;
}CLNode, *CLLinkList;

2.单循环链表的建立

void CreateListR(CLLinkList& L, int n)                
{
    L = new LNode;
    LinkList p;
    LinkList ptail = L;                
    ptail->next = NULL;
    while (n--)
    {
        p = new LNode;
        cin >> p->data;
        ptail->next = p;
        ptail = p;
    }
    ptail->next = L;
}

结构特点:链表呈环状,可以从链表的任意位置对整个链表进行遍历

1.2 学习体会

使用链表存储数据较为简便,方便对存储数据进行插入、删除等改动。
在学习过程中,主要遇到的问题有两点:
1.开始的时候对链表的操作不熟练,导致循环时判断条件的使用错误,导致循环结束的位置不正确。
2.在使用循环的时候因为没有转换思维,喜欢使用两层循环,导致提交时产生运行超时的问题。

2.PTA实验作业

2.1 有序链表合并

  • 2.1.1 代码截图
  • 2.1.2 本题PTA提交列表说明

    Q1:第一次在合并链表的时候,遇到相同元素我并未删除,而是将两个元素一起放入链表。
    A1:发现这个问题之后,在两个数据相同是,我删除了第二个表的数据,将第一个表的数据放入新合并的表中

2.2 有序链表合并

  • 2.1.1 代码截图
  • 2.1.2 本题PTA提交列表说明

    Q1:第一次因为分割时操作不当导致原有链断裂,导致代码运行出错
    A1:新开辟结点存储数据,加入第二条链,是原有链不断裂
    Q2:未注意题中的要求第二条链为倒序
    A2:对第二条链使用头插法

2.2 有序链表合并

  • 2.1.1 代码截图


  • 2.1.2 本题PTA提交列表说明

    Q1:第一次使用链表存储,导致存储时代码出问题,无法编译
    A1:后使用数组存储,内容存储系数,下表为指数

3.阅读代码

3.1 题目及解题代码

猜你喜欢

转载自www.cnblogs.com/whb1/p/12395316.html
今日推荐