博客作业2---线性表

一、PTA实验作业

题目1:顺序表删除重复元素

1. 设计思路

1.建表函数CreateSqList:
定义建表函数CreateSqList(List &L,int a[],int n)
    为L分配空间
    for    int i=0    to    n-1
        把数组a的数据分别赋给L->data[i]
    L->length=n;
2.输出函数DispSqList
定义输出函数DispSqList(List L)
    定义count为0
    for int i=0    to    L->length-1
        如果count=0
            输出L->data[i],count++
        否则输出空格加L->data[i]
3.删除函数DelSameNode
定义删除DelSameNode(List &L)
    定义i,j=0;
    定义数组a[100],b[maxsize],left[maxsize];
    初始化数组a,b为0
    for    i=0    to    L->length-1
        a[L->data[i]]++;
    for    i=0    to    L->length-1
        如果a[L->data[i]]>1&&b[L->data[i]]!=0
            a[L->data[i]]--;直接进行下一次循环
        left[j]=L->data[i];
        j++;
    b[L->data[i]]++;
    for    i=0    to    j-1
        L->data[i]=left[i];
    L->length长度赋值为j

2.代码截图

3.PTA提交列表说明

第一次提交时答案错误,经调试后发现,数组没有初始化导致答案错误,于是就写了个初始化的代码,提交后格式错误,想起我没有控制末尾无空格,改了之后答案正确。

题目2:单链表逆置

1. 设计思路

1.建链表函数CreateSqList:
 定义函数CreateList(List &L,int n)
    为L分配空间,L->next置空
    定义List型变量p,tail
    定义int型变量i
    tail=L;
    for    i=0    to    n-1
        为p分配空间
        输入p->data
    tail->next=p;
    tail=p;
    p->next=NULL;//尾插法连接
2.打印链表函数PrintList
定义函数PrintList(List L)
    定义flag=0
    如果L为空
        输出NULL
    while(L)
        如果flag为0
            输出L->data,flag++
        否则输出空格加L->data
        L=L->next      
3.逆置链表函数ReverseList
定义函数ReverseList(List &L)
    定义List型变量newhead=NULL,tail=NULL,p;
    p=L->next
    while(p)
    tail=p->next;
    p->next=newhead;
    newhead=p;
    p=tail;//逆置链表,头指针为newhead
    newhead赋值给L

2.代码截图

3.PTA提交列表说明

提交后发现链表不空时格式错误,检查代码时发现没有控制末尾无空格。

题目3:两个有序序列的中位数

1. 设计思路

链表结点定义:
typedef struct LNode
{
ElemType data;
    struct LNode *next;
} LinkList,*List;
1.建链表函数CreateListR:
 定义函数CreateListR(List &L,int n)
    为L分配空间,L->next置空
    定义List型变量p,tail
    定义int型变量i
    tail=L;
    for    i=0    to    n-1
        为p分配空间
        输入p->data
    tail->next=p;
    tail=p;
    p->next=NULL;//尾插法连接
2.打印函数DispList
定义函数DispList(List L,int n)
    定义整型变量i
    for    i=1    to    n
        L=L->next
    输出L->data
3.求并集函数Union
定义函数Union(List S1,List S2,List &S3)
    定义List型变量p,tail
    为S3分配空间
    tail=S3;
    while(S1&&S2)//二路归并求并集
        如果S1->data<S2->data
            把S1->data连接进S3链表中
        否则把S2->data连接进S3链表中
    判断S1,S2哪个还未遍历完
        未遍历完的把余下的数值都连接进S3链表中

2.代码截图

3.PTA提交列表说明

提交时部分正确,检查代码并调试,输入不同的例子去检查,发现有些例子会出现错误,后来发现输出函数的循环条件出现错误,是我看错了题目的意思,改过来就正确了。

二、截图本周题目集的PTA最后排名

1.顺序表PTA排名

2.链表PTA排名

3.我的总分

267

三、本周学习总结

1.谈谈你本周数据结构学习时间是如何安排,对自己安排满意么,若不满意,打算做什么改变?

对于学习时间的安排我并没有很明确的计划,当有新的课堂派发布需要去预习的时候我就会去预习课本,每上完一节课后对于一些没弄懂的知识,继续去学习,争取早一点把不懂的知识点解决。对于编程时间的安排,就是当有pta发布时,有空闲的时间我就会去做。对于自己的安排,我感觉还好。

2.谈谈你对线性表的认识?

  • 主观认识:线性表是最基本、最简单、也是最常用的一种数据结构。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。
  • 线性表有顺序储存和链式储存两种储存方式。其中顺序表储存中物理地址是相邻的,可以实现随机存取。顺序表无需为表示表中元素之间的顺序关系增加额外的储存空间,但是插入删除操作需要移动大量元素,效率比较低,而且预先分配空间难以充分利用。链表储存地址是随机的,链表中插入删除操作相对于顺序表来说比较简便。链表分为无头结点的链表,带头结点的链表,双链表,循环链表。对于这些线性表要熟练掌握其相关的建表,插入,删除等操作。

3.代码Git提交记录截图

四、阅读代码

1.题目

选首领。N个游戏者围成一圈,从第一个开始顺序报数1,2,3.凡报到3者退出圈子,最后留在圈中的人为首领。

2.代码

#include <stdio.h>  
#include <stdlib.h>  
typedef struct node{  
      int   code;          /*  游戏者的编号 */  
      struct node *next;  
}NODE,*LinkList;  
LinkList  create_list(int n)  
/* 创建一个节点数为n的单循环链表,返回值为游戏编号为1的节点的指针  */  
{ LinkList head,p;  
  int i;  
  head=(NODE*)malloc(sizeof(NODE));/*创建循环链表的第一个节点*/  
  if(!head){  
     printf("内存位置错误!/n");return NULL;  
  }  
  head->code=1;  head->next=head;  
  for(i=n;i>1;--i){/* 尾插法创建循环链表的其余n-1个节点*/  
     p=(NODE*)malloc(sizeof(NODE));  
     if(!p){  
         printf("内存位置错误!/n");return NULL;  
     }  
     p->code=i;  p->next=head->next; head->next=p;  
  }/*for*/  
  return head;  
}/*create_list*/  
void output(LinkList head)/*输出链表中的节点的数据*/  
{   LinkList p;  
    p=head;  
    do{  
       printf("%4d",p->code);  p=p->next;  
    }while(p!=head);  
     printf("/n");  
}/*output*/  
void play(LinkList head,int n)  
{   LinkList p,q;  
    int c=0,k;  
    p=head; c=1;k=n;  
    while(k>1){  
        if(c==2){  /* 当c等于2时,p指向的节点后继即为被删除的节点*/  
           q=p->next;p->next=q->next;  
           printf("%4d",q->code); free(q);  
           c=0;  k--;  
        }/*if*/  
        else{c++;p=p->next;}  
    }/*while*/  
    printf("/n%4d 是首领.",p->code);  /*输出最后留在圈子内的人的编号*/  
}/*play*/  
void main(void)  
{ LinkList head;    
  int n;  
  printf("请输入游戏者的游戏编号:"); scanf("%d",&n);  
  head=create_list(n);               /*创建单循环链表*/  
  if(head){   
  output(head);                      /*输出单循环链表中的节点的信息*/  
  play(head,n);  
  }  
}

3.优点

这个题目在上个学期也有做过,那就是猴子选大王那一道题目,以前是用数组做的,现在这个程序是用链表做的,感觉挺巧妙的,方法是创建一个包含N个节点的单循环链表来模拟N个人围成的圈。节点的数据域存放游戏者的编号。
在程序中,以删除节点模拟人退出圈子的处理,整型变量c(初始值为1)用于计数,指针变量p的初始值为head,运行时,从p所指的节点开始计数,p沿链表中的指针每次向后指一个节点,c值随p指针的移动相应地递增。当c计数到2时,就删除下一个节点,然后将c置为0。为了避免将剩下的最后一个节点删除,另外设置一个计数器k,其初值为参加游戏的人数。每当删除一个节点时,k值就减1,当k等于1时,首领就选出来了。

posted @ 2018-03-25 23:11  久念  阅读(418)  评论(2编辑  收藏  举报