zoukankan      html  css  js  c++  java
  • DS博客作业01--线性表

    [DS博客作业01--线性表]

    这个作业属于哪个班级 数据结构--网络2011/2012
    这个作业的地址 DS博客作业01--查找
    这个作业的目标 学习线性表的相关结构
    姓名 姚庆荣

    0. PTA得分截图

    1.本周学习总结(5分)

    1.1 绪论(1分)

    1.1.1 数据结构有哪些结构,各种结构解决什么问题?

    • 逻辑结构(图表和二元组):

    集合:元素同属一个集合;

    线性结构:数据元素关系一对一,除开始元素和终端元素唯一外,其余元素都仅有一个前驱元素和一个后继元素;

    树形结构:数据元素关系一对多,除开始元素唯一,终端元素不唯一,其余元素有一个或多个后继元素;

    图形结构:数据元素关系一对多,开始和终端元素数量任意,且其余元素的前驱元素和后继元素可有多个;

    • 存储结构:

    顺序存储结构:采用一组连续的存储单元存放所以数据元素;

    链式存储结构:每个元素有一个对应的内存结点,结点地址不一定连续,通过指针链接结点;

    1.1.2 时间复杂度及空间复杂度概念。

    计算算法的频度T(n):T(n)与计算算法执行的时间成正比,与操作时间大致相同;

    时间复杂度O(n):T(n)=O(f(n)),也称渐进时间复杂度,随问题规模n的增大,算法执行时间的增长率与f(n)的增长率相同;是对时间增加趋势的分析;

    空间复杂度S(n):S(n)=O(g(n)),是对一个算法在运行过程中临时占用存储空间大小的量度;只考虑临时空间;

    1.1.3 时间复杂度有哪些?如何计算程序的时间复杂度和空间复杂度,举例说明。

    时间复杂度的种类:常数阶O(1),对数阶O(),线性阶O(n),线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),...,k次方阶O(nk),指数阶O(2n);

    例:

    int i=0;
    int j=0;
    while(i<n){
      while(j<n){
        j++;
      }
      i++;
    }
    

    算法计算的时间为两层n循环,时间复杂度与最高的次方阶有关,时间复杂度为O(n2),空间复杂度也为O(n2);

    1.2 线性表(1分)

    1.2.1 顺序表

    • 介绍顺序表结构体定义、顺序表插入、删除的代码操作

    定义:

    /*线性表的定义*/
    typedef struct
    {
           char *elem;
           int length;//当前长度
           int listsize;//线性表的长度
    }SqList;
    

    插入:

    void Insert(sq_list_ *l,int i, int x) {
    	//先判满,看顺序表是否还有空间能装得下新元素
    	if (l->length >= MAX) {
    		std::cout << "
    the list is full!
    ";
    		return;
    	}
    	//然后判断选择插入的索引位置是否合理
    	//已有元素的索引为0---length-1,所以插入元素的范围只能是 0---length,
    	if (i<0 || i>l->length) {
    		std::cout << "
    invalid index: "<<i<<"! the index should be 0 - "<< l->length<<" 
    ";
    	}
    	//把i位置及其之后的元素都后移一位
    	int j;
    	for (j = l->length - 1; j > i; j--)
    		l->data[j + 1] = l->data[j];
    	l->data[i] = x;//在i位置赋值x
    	l->length++;//更新表长
    }
    

    删除:

    void Delete(sq_list_ *l, int i) {
    	//判空
    	if (l->length<=0) {
    		std::cout << "	he list is empty!
    ";
    		return;
    	}
    	if (i<0 || i>l->length - 1) {
    		std::cout << "
    invalid index: "<<i<<"! the index should be 0 - " << l->length-1 << " 
    ";
    		return;
    	}
    	for (int j = i; j < l->length - 1; j++)
    		l->data[j] = l->data[j + 1];
    
    	l->length--;
    }
    
    • 介绍顺序表插入、删除操作时间复杂度

      如果插入和删除的是最后一个元素,那么时间复杂度是O(1);

      如果是插入和删除的是第一个元素,那么时间复杂度是O ( n );

      如果是插入和删除的是第i个元素,那么时间复杂度是O(n-i);

      所以顺序表时间复杂度O(n)。

    1.2.2 链表(2分)

    • 画一条链表,并在此结构上介绍如何设计链表结构体、头插法、尾插法、链表插入、删除操作

    结构体:

    typedef struct Node
    {
    ElemType data;
    struct Node *next;
    }Node;
    

    头插法:

    oid CreateList_b(LinkList Lb)            //头插法 
    {
        int s_f,flag=1;
        Node *p;
        p=Lb;
        printf("Please enter Lb data and enter 0 over:
    ") ;
        while(flag)
        {
            scanf("%d",&s_f);
            if(s_f!=0)
            {
                p=(LinkList)malloc(len);
                p->data=s_f;
                p->next=Lb->next;
                Lb->next=p;
            }
            else
                flag=0;
        }
    }
    

    尾插法:

    void CreateList_a(LinkList La)          //尾插法 
    {
        int s_f,flag=1;
        Node *p1,*p2;
        p1=La;
        printf("Please enter La data and enter 0 over:
    ") ;
        while(flag)
        {
            scanf("%d",&s_f);
            if(s_f!=0)
            {
                p2=(LinkList)malloc(len);
                p2->data=s_f;
                p1->next=p2;
                p1=p2;
            }
            else
            {
                flag=0;
                p1->next=NULL;
            }
        }
    }
    

    链表删除:

    void deleteLinkedList(LinkedList L,int i)//删除链表上的元素
    {
        int j;
         LinkedList p,q;
         p=L;
         j=1;
         while(j<i)
         {
             p=p->next;
             j++;
         }
         q=p->next;
         p->next = p->next->next;
         free(q);
    }
    
    • 重构链表如何操作?链表操作注意事项请罗列。

      1. 链表的非空判断;
      2. 对链表结点的next关系进行修改之前,一般注意保留后继结点;
        链表有无头结点
      3. 遍历时要记住新建遍历指针,一般不要将指向头结点的头指针拿去当遍历指针;
      4. 链表的类型:单链表,循环单链表,循环双链表等;
      5. 删除结点后,记得delete;
    • 链表及顺序表在存储空间、插入及删除操作方面区别,优势?

    1.2.3 有序表及单循环链表(1分)

    • 有序顺序表插入(以递增为例):

    img

    img

    img

    代码:

        // insert_num  为插入的数据
        int position = 0;    // 存放要插入的位置
    
        for(i = L->length - 1; i >= 0 && L->data[i] < insert_num; i--)
        {
             L->data[i + 1] = L->data[i];
        }
        position = i+1;    //找位置
    
        L->data[position] = insert_num;    //插入
        L->length++;    //增加长度
    
    • 有序单链表插入、删除(以递增为例):

      img

    代码:

        LinkList pre = L;
        while(pre->next && pre -> next > insert_num )  //遍历,寻找插入位置的前驱
        {
             pre = pre->next;
        }
        
        LinkList node = new LNode;    //新建结点,存放插入数据
        node->data = insert_num;
        
        node->next = pre->next;     //修改next关系,完成插入
        pre->next = node;
    
    • 有序链表合并:

      img

    代码:

         LinkList pL1 = L1->next;    //新建遍历指针
         LinkList pL2 = L2->next;
    
         LinkList merge_L = L;      //重构链表
         L->next = NULL;
    
         while(pL1 && pL2)          //任一为空时结束循环
         {
              if(pL1->data == pL2->data)  //相同
              {
                   merge_L -> next = pL1;
                   merge_L = merge->next;
    
                   pL1 = pL1 ->next;
                   pL2 = pL2 ->next;
              }
              else if(pL1->data < pL2->data)  
              {
                   merge_L -> next = pL1;
                   merge_L = merge->next;
                    
                  pL1 = pL1 ->next;
              }
              else 
              {
                   merge_L -> next = pL2;
                   merge_L = merge->next;
    
                   pL2 = pL3->next;
              }
         }
    
          if(pL1)    //若pL1所指向为空,则pL2剩下的数据元素接到merge_L的后面
              merge_L ->next = pL2;
          else
              merge_L ->next = pL1;
    

    有序链表合并的优势:

    1)有序顺序表合并需要新建一个数组;有序链表可以在原链表上进行重构,更节省空间

    2)若合并的某个表先为空,有序顺序表需要将剩下的元素遍历存入重构数组中;而有序链表仅仅修改next关系即可

    单循环链表特点,循环遍历方式:

    • 特点:
      1)尾结点的next不指向NULL,而是指向头结点
      2)可以从任何位置开始遍历整个链表
    • 遍历:
        LinkList p = L->next;  
        while(p != L)    //与单链表不同的是,将 p!= NULL 改为了p!= L
        {
             ...
             p = p->next;
        }
    

    2.PTA实验作业(4分)

    2.1 两个有序序列的中位数

    2.1.1 解题思路及伪代码

    定义 S1,S2, total;
    
    输入长度N;
    
    for(i=0 to n)
    
    输入集合S1
    
    end for
    
    for(i=0 to n)
    
    输入集合S2
    
    end for
    
    for(t=0 to t<2*n)
    
    if(对应S2中元素大于等于S1)
    
    total[]=S1[];
    
    end if
    
    else if(对应S2中元素小于于S1)
    
    total[]=S2[];
    
    end if
    
    end for
    
    输出中位数;
    

    2.1.2 总结解题所用的知识点

    • 未使用链表的方式进行编码,使用c中的for循环语句和if语句的不同情况进行判断,计算出中位数。

    2.2 一元多项式的乘法与加法运算

    2.2.1 解题思路及伪代码

    // 多项式合并:
    LinkList MergeList(LinkList L1, LinkList L2)
    {
            pL1 = L1 ->next;
            pL2 = L2 -> next; 
            tail = L1;        
    
            L_merge = L1;
            L_merge->next = NULL;
            
            while(pL1 != NULL && pL2 != NULL)  do
            {
                if( pL1 -> index = pL2 ->index)  //如果指数相等
                {
                       pL1->coefficient = pL1->coefficient + pL2->coefficient;//系数相加,存放在pL1中
                       再将pL1所指的结点接到tail后面;
                       tail = tail->tail;    //tail移动
                       pL1、pL2移动;
                 }end if
                  
                 else if (pL1 ->index > PL2 ->index) 
                 {
                       将pL1所指的结点接到tail后面;
                       tail = tail->tail;    //tail移动
                       pL1移动;
                 } end else if
    
               //...pL2所指结点的指数大时,处理情况与pL1大类似,不多赘述
            }end while
          
            if(pL1)  //如果while循环结束,pL1仍剩余
                tail ->next = pL1;
            end if
            else 
                 tail ->next = pL2;
            end else
    
            return L_merge;  //返回头结点
    }
    
    
    
    // 多项式相乘:
    LinkList MultiplyList(LinkList L1, LinkList L2)
    {
         新建LinkList指针L_multiply(头结点)存放最终相乘后的多项式
         新建LinkList指针L_temp,存放计算过程中多项式
    
          while(pL1)
          {
                L_temp->NULL;      //每轮开始时,重构L_temp;
                tail = L_temp;
                pL2 = L2->next;    //每轮初始化pL2
      
                while(pL2)
                {
                      新建node结点,并分配内存;
                    //node的介绍:node结点存放pL1所指的数据与pL2所指的数据相乘;
      
                      node->index = pL1->index + pL2->index;
    	          node->coefficient = pL1->coefficient * pL2->coefficient;
                  
                      将node接到tail后面;
                      tail、pL2移动到后一个结点
                }
                tail -> next = NULL;  //尾结点的next为空
                将pL1移动到后一位  
          
                调用函数MergeList(),将L_multiply和L_temp合并,
                合并后的多项式在L_multiply中
          }end while
           return L_multiply;
    }end while
    

    2.2.2 总结解题所用的知识点

    • 多项式合并,用到了链表合并的知识点:链表重构,尾插法、链表遍历
    • 多项式相乘,用到了尾插法新建链表、调用函数

    3.阅读代码(1分)

    3.1 题目及解题代码

    • 题目描述

    判断给定的链表中是否有环。如果有环则返回true,否则返回false。

    class Solution {
    public:
        bool hasCycle(ListNode *head) {
            ListNode* fast = head;
            ListNode* slow = head;
            while(slow!=NULL&&fast->next!=NULL&&fast->next->next!=NULL)
            {
                fast = fast->next->next;
                slow = slow->next;
                if(fast==slow)
                {
                    return true;
                }
            }
            return false;
        }
    };
    

    3.2 该题的设计思路

    设计思路:

    使用快慢指针,指针p1每次移动一个结点,指针p2每次移动2个结点,若p1、p2相遇则证明环存在

    • 算法的时间复杂度:算法中涉及一个循环,时间复制度为O(n)
    • 空间复杂度:临时变量占用的临时存储空间与问题规模无关,空间复制度为O(1)

    3.3 分析该题目解题优势及难点。

    • 题解优势:使用了快指针和慢指针解决了分析链表是否有环的问题。
    • 延申:在查找倒数第k个数据元素时也可以使用类似的两个指针遍历的方式:一个指针1先走k个位置,之后指针2再和指针1一起开始移动,当指针1为空时,指针2所指的数据元素就是倒数第k个元素。
    • 难点:是否考虑到快慢指针的使用
  • 相关阅读:
    【java基础知识】1
    【android】工程基本文件介绍
    【sqlite权威指南】笔记3 sqlite入门
    【sqlite权威指南】笔记2 sqlite介绍
    【sqlite权威指南】笔记1 概述
    【sqlite】1 start
    【操作系统】笔记8 存储器
    【操作系统】笔试7 汇编
    【操作系统】笔记6 java基本类型及运算
    【操作系统】笔记5
  • 原文地址:https://www.cnblogs.com/yqr2012/p/14882925.html
Copyright © 2011-2022 走看看