博客作业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时,首领就选出来了。