博客作业2---线性表

一、PTA实验作业(5分)

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

2. 设计思路(伪代码或流程图)

新建顺序表函数:
应用地址L,传入数组a【】和长度n
L申请空间
定义变量i
for(i=0;i<n;i++)
    将数组a中元素转移到L中
L的长度改为n

展示表中元素函数:
传入顺序表L
定义变量i
for(i=0;i<L->length;i++)
    输出L->data[i]
    不到最后一个元素都输出空格

删除相同元素函数:
引用顺序表L
定义变量i,j,k
for(i=1;i<L->length;i++){
    for(j=0;j<i;j++){
        if(L->data[i]==L->data[j])找到相同元素
		移动后面元素删除相同元素
		L长度减少
		i--,从该位置开始判断
    end
end

3.代码截图

4.PTA提交列表说明。


该题提交结果提交时,只出现了段错误,没有其他的错误,一直找不到原因,一直修改删除相同数据的函数,不断提交,结果最多就只有空表的数据点正确。
解决方法:看了一眼其他同学的代码,发现新建顺序表时,没有给L申请空间,但是devc++编译没出现问题,所以一直没发现,修改后就对了。

题目2:jmu-ds-单链表逆置

2. 设计思路(伪代码或流程图)

新建单链表函数:
应用地址L,传入长度n
新建指针p和tail
L申请空间
初始化L为空的单链表
tail赋值L,形成尾指针
定义int变量num存元素
while(n--)
    输入num
    p节点申请空间
    p->data变为num
    p->next为空
    连接p与L
    尾节点移动到p
end

展示表中元素函数:
传入单链表L
定义指针l进行链表间移动
if(L为空链表)输出NULL
while(l不为空)
    输出l->data
    不到最后一个元素都输出空格
    l移动到下一个节点
end

单链表逆序函数:
引用单链表L
定义List指针p=L->next得到L的后续节点,并定义一个q暂存节点
L链表初始化为空
while(p不为空时)
    q从p中取出一个节点
    p移动到下一个
    q节点为插到L的后面
end

3.代码截图


4.PTA提交列表说明。


思路清晰,在devc++上验证好多遍,上交后有一个错误:空表时格式错误,结果是因为输出时没检查空表,加上一句判断后结果正确。

题目3:集合的基本运算

2. 设计思路(伪代码或流程图)

新建单链表函数:
应用地址L,传入长度n和数组a
新建指针p和tail
L申请空间
初始化L为空的单链表
tail赋值L,形成尾指针
定义变量i
for(i=0;i<n;i++)
    p节点申请空间
    将数组a中元素转移到p->data
    p->next为空
    连接p与L
    尾节点移动到p
end

展示表中元素函数:
传入单链表L
定义指针l进行链表间移动
if(L为空链表)输出NULL
while(l不为空)
    输出l->data加空格
    l移动到下一个节点
输出换行
end

摧毁单链表函数:
引用L
定义链表指针p
while(L)
    p=L
    L下移
    删除p
end

排序的函数:
引用L
定义链表指针p继承L后续节点,q存放取出的节点,l在新建链表上移动,pre用于连接
L->next=NULL
while(p)
    q=p取出节点
    p下移
    if第一个节点,直接插入
    else
        pre=L
        l=L->next
        while(l不为空)
            if(l->data大于q->data)
                插入q在该元素前面
                停止循环
            if(l到达尾)
                q直接插到末尾
                停止循环
            l指向下一个
        end
end

求并集的函数:
传入ha,hb,引用hc
定义链表指针p和tail当成尾节点
hc申请空间并初始化
尾节点初始化到hc
ha=ha->next;hb=hb->next从有效点开始操作
while(ha||hb)两条链表都结束才结束
    p申请空间
    if(hb为空或ha->data小于hb->data)
        ha的data给p的data
        p->next为空
        连接p到hc
        ha移动到下一个
    else if(ha为空或ha->data大于hb->data)
        hb的data给p的data
        p->next为空
        连接p到hc
        hb移动到下一个
    else if(ha->data等于hb->data)
        hb的data给p的data
        p->next为空
        连接p到hc
        ha,hb移动到下一个
end

求交集函数:
传入ha,hb,引用hc
定义链表指针p和tail当成尾节点
hc申请空间并初始化
尾节点初始化到hc
ha=ha->next;hb=hb->next从有效点开始操作
while(ha||hb)两条链表都结束才结束
    p申请空间
    if(hb为空或ha->data小于hb->data)
        ha移动到下一个
    else if(ha为空或ha->data大于hb->data)
        hb移动到下一个
    else if(ha->data等于hb->data)
        hb的data给p的data
        p->next为空
        连接p到hc
        ha,hb移动到下一个
end

求差集函数:
传入ha,hb,引用hc
定义链表指针p和tail当成尾节点,h存ha和hc交集
h申请空间并初始化
调用函数求ha和hc交集到h
hc申请空间并初始化
尾节点初始化到hc
ha=ha->next;h=h->next从有效点开始操作
while(ha||h)两条链表都结束才结束
    p申请空间
    if(h为空或ha->data小于h->data)
        ha的data给p的data
        p->next为空
        连接p到hc
        ha移动到下一个
    else if(ha为空或ha->data大于h->data)
        h的data给p的data
        p->next为空
        连接p到hc
        h移动到下一个
    else if(ha->data等于hb->data)
        ha,hb移动到下一个
end

3.代码截图





4.PTA提交列表说明。


开始的错误有段错误和答案错误,多错误的原因就是空指针是让他指向了data,修改了循环和一些条件就可以了,改动的地方很多很杂,不便具体指出,然后就是答案错误,具体原因是求差集的函数理解错误,以为是a并b-a交b,结果是a-b,理解后改了下就对了。

二、截图本周题目集的PTA最后排名(3分)

1.顺序表PTA排名

2.链表PTA排名

3.我的总分:270

三、本周学习总结(2分)

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

学习时间都是预习作业一出来就开始本章的预习,先翻翻课本了解一下,在通过课堂派的习题深入了解知识点,等到真正上课时认真听老师讲解本章的知识点,稍微记录下老师讲过的但课本上没有的重要内容,最后通过pta综合一下,融会贯通,能熟练运用于实践的代码编程。编程的时间安排一般是找时间比较长的时间段,不如晚自习放学回宿舍,或礼拜天,一起做几题出来,一般一个时间段能做三四题。不懂问题时一般先在宿舍内讨论下,基本能得到解决。安排还算满意,能够保持下去就可以了。

2.谈谈你对线性表的认识?(1分)

线性表就是将一串数据连接起来成线性结构,方便对这串数据进行操作的一种结构.
线性表主要主要有两种存储结构:顺序结构和链式结构
1.顺序结构/顺序表
顺序表在计算机内占有一块连续的内存,可以通过下标直接访问到表中元素,但是删除表中元素时就要对其他元素做移动。
结构体定义样例:

struct LNode {
    ElementType Data[MAXSIZE];
    Position Last; /* 保存线性表中最后一个元素的位置 */
};

基本操作合集:

//销毁顺序表 
void FreeList_sq(SqList &L){  
    if (L.elem)   
    free(L.elem);  
    printf("完成链表内存销毁\n"); 
}    
//在顺序表的第i个位置之前插入新元素 
int ListInsert_sq(SqList &L, int i, ElemType e){  
    int k;  
    if (i<1 || i>L.length + 1) 
        return ERROR; /*插入位置不合法*/  
    if (L.length >= L.listsize){     /*存储空间满,重新分配空间*/   
        L.elem = (ElemType*)realloc(L.elem, (LIST_INIT_SIZE + INCREM)*sizeof(ElemType));   
        if (!L.elem) return OVERFLOW;      /*存储分配失败*/   
            L.listsize += INCREM;             /*修改存储空间大小*/  
    }  
    for (k = L.length - 1; k >= i - 1; k--){      /*插入位置之后元素后移*/   
        L.elem[k + 1] = L.elem[k];  
    }  
    L.elem[i - 1] = e;                     /*插入元素*/  
    L.length++;                         /*顺序表长度加1*/  
    return OK; 
}/*ListInsert*/    
//遍历并输出顺序表所有元素 
void PrintList_sq(SqList &L){  
    if (!L.elem)   return;   
    int i = 0;      
    for (i = 0; i < L.length; i++)   
        printf("第[%d]元素= [%d]\n", i, L.elem[i]); 
}   
//删除顺序表第i个位置的元素  
int ListDelete_sq(SqList &L, int i,ElemType &e){  
    int k;  
    if (i<1 || i>L.length) 
    return ERROR; /*删除位置不合法*/  
    e = L.elem[i-1];  
    for (k = i - 1; k<L.length - 1; k++)       /*元素前移*/   
        L.elem[k] = L.elem[k + 1];  
        L.length--;                       /*顺序表长度减1*/  return OK; 
}   
//在顺序表里查找出第1个与e相等的数据元素位置 
int LocateElem_sq(SqList L,ElemType e){ 
     int i = 0;  
    while(i<=L.length){   
        if(L.elem[i] == e)     
            break;   
        else    
            i++;  
    }  
    if(i<=L.length) 
        return i;  
    return -1; 
}   
//已知线性表La和Lb的元素按值非递减排列  //归并后的La和Lb得到新的顺序线性表Lc,Lc的元素也是按值非递减排列 
void MergeList_sq(SqList La,SqList Lb, SqList &Lc){  
    ElemType *pa = La.elem;  
    ElemType *pb = Lb.elem;  
    Lc.listsize = Lc.length = La.length + Lb.length;   
    if(!Lc.elem) exit(OVERFLOW); //存储分配失败  
    int i = 0,j = 0;   
    int k =0;    //i指向La的当前位置,j指向Lb当前位置,k指向Lc当前位置  
    while(i<La.length && j<Lb.length){   //归并   
        if(La.elem[i]<Lb.elem[j]){     
            Lc.elem[k] = La.elem[i];    
            i++;   
        }   
        else{    
            Lc.elem[k] = Lb.elem[j];    
            j++;   
        }   
        k++;  
    }  
    while(i<La.length) 
        Lc.elem[k++] = La.elem[i++];  
    while(j<La.length) 
        Lc.elem[k++] = Lb.elem[j++];   
}
//判断顺序表是否为空
bool ListEmpty(SqList &L){ 
    if(L.length > 0)  
        return 1;  
    else   
        return 0; 
}

2.链式结构/单链表,双链表,循环链表
链表存储更叫灵活,不依赖物理上内存的位置,可以进行任意的增加和删除,即增加减少节点即可,但是查找时这要遍历链表方能找到。
结构体定义:

typedef char ElemType;
typedef struct LNode	//定义单链表结点类型
{
  ElemType data;
  struct LNode *next;
} LinkList;

基本操作集合:

//销毁单链表表  
void FreeList_L(LinkList L){   
    LinkList p = L;  
    while (p){   
        L = L->next;   
        free(p);   
        p = L;  
    }  
}    
//在单链表的第i个位置之前插入新元素  
Status ListInsert_L(LinkList &L, int i, ElemType e){  
    LinkList p = L;   
    int j = 0;  
    while(p && j<i-1){  //寻找第i-1个结点   
        p = p->next;   
        ++j;  
    }  
    if(!p || j>i) 
        return ERROR;  
    LinkList s = (LinkList)malloc(sizeof(LNode));  
    s->data = e;  
    s->next = p->next;  
    p->next = s;  
    return OK; 
}     
//遍历并输出单链表所有元素 
void PrintList_L(LinkList L){  
    int i = 0;  
    LinkList p = L->next;  
    while (p){   
        printf("第[%d]元素= [%d]\n", i++, p->data);   p = p->next;  
    }   
}  
//获取单链表第i个位置的元素  
Status GetElem_L(LinkList L,int i,ElemType &e){  //L为带头结点的单链表的头指针  
//当第i个元素存在,其值赋给e并返回OK,否则返回ERROR  
    LinkList p = L->next;  
    int j = 1;  
    while(p && j<i){   
        p = p->next;   
        ++j;  
    } 
     if(!p) 
        return ERROR; //第i个元素不存在  
    e = p->data;  
    return OK; 
}   
//删除单链表第i个位置的元素,并由e返回其值 
Status ListDelete_L(LinkList &L, int i, ElemType &e){  
    LinkList p = L;   
    int j = 0;  
    while(p->next && j<i-1){  
        //寻找第i个结点,并令p指向其前驱   
        p = p->next;   
        ++j;  
    }  
    if(!p->next || j>i-1) 
        return ERROR;  //删除位置不合理  
    LinkList q = p->next;  
    p->next = q->next;  
    e = q->data;  
    free(q);  
    return OK;  
}   
//单链表翻转,不增加额外的存储空间 
void ListConvert_L(LinkList &L) {  
    LinkList p,q;  
    p=L->next;  
    L->next=NULL;  
    while(p){   
        q=p;   
        p=p->next;   
        q->next=L->next;   
        L->next=q;  
    } 
}

3.代码Git提交记录截图

四、阅读代码(选做,加1分)

找1篇优秀代码贴图展示,并说明该代码功能是什么,优点是什么?
代码可以是自己同学代码,也可以是其他地方找的代码。
线性表合并运算函数:

void mergeList(SeqList *LA, Seqlist *LB, Seqlist *LC)
{
    int i,j,k;
    i=0; j=0; k=0;
    while(i <= LA->last || j <= LB->last)
    if(LA->elem[i] <= LB->elem[i] || (i <= LA->last && j > LB->last  ))
        {
            LC->elem[k] = LA->elem[i];
            i++; k++;
        }

    if(LA->elem[i] > LB->elem[j] || (i > LA->last && j <= LB->last))
        {
            LC->elem[k] = LB->elem[i];
            j++; k++; 
        }
}

功能:将两条顺序表中的元素合并并从小到大排列。
优点:循环结束的条件是两条有序的线性表都走到空时才停止循环,虽然有可能出现下标越界的风险但是合理控制了这种情况,利用条件判断,当一条链表为空时,填入另一条链表的值,是程序大大简化。

posted on 2018-03-25 21:47  斯慕  阅读(214)  评论(2编辑  收藏  举报