• DS博客作业02--线性表


    0.PTA得分截图


    1.本周学习总结

    1.1 线性表

    · 顺序表结构体

    
    typedef int ElemType;
    typedef struct 
    {   
        ElemType data[MaxSize];     //存放顺序表元素
        int length ;                //存放顺序表的长度
    } List; 
    
    

    · 创建循序表

    
    void CreateList(SqList& L, int n)//构建顺序表函数 ,n为顺序表长度
    {
        L = new List;
        L->length = n;
        for (int i = 0; i < n; i++)
        {
            cin >> L->data[i];
        }
    }
    
    

    · 顺序表插入

    
    bool Insert(List L, ElementType X, Position P)//X表示要插入的元素,P表示插入位置
    {
    	if (L->Last + 1 == MAXSIZE)//顺序表已满
    	{
    		printf("FULL");
    		return false;
    	}
    	int i;
    	if (P<0 || P>(L->Last + 1))
    	{
    		return false;//位置非法
    	}
    	for (i = L->Last; i >= P; i--)
    	{
    		L->Data[i + 1] = L->Data[i];
    	}
    	L->Data[P] = X;
    	L->Last++;//最后一个位置下标++
    	return true;
    }
    
    

    · 顺序表删除

    
    bool Delete(List L, Position P)//P表示要插入的位置
    {
    	if (P<0 || P>(L->Last + 1))//非法访问
    	{
    		return false;
    	 }
    	int i;
    	for (i = P; i <= L->Last-1; i++)
    	{
    		L->Data[i] = L->Data[i + 1];//从第i个元素开始,之后的元素往前移
    	}
    	L->Last--;//最后一个位置的下标--
    	return true;
    }
    
    

    · 单链表结构体定义

    
    typedef struct LNode //定义单链表结点类型
    {
        ElemType data;
        struct LNode *next;//指向后继结点
    } LNode,*LinkList;
    
    

    · 两种建立链表的方式

    (1)尾插法

    void CreateList(LinkList& L, int n)
    {
        LinkList tail, p;
        L = new LNode;
        tail = L;
        L->next=NULL;
        for (int i = 0; i < n; i++)
        {
            p = new LNode;
            cin >> p->data;
            p->next = NULL;
            tail->next = p;
            tail = p;
        }
    }
    
    

    图解:

    (2)头插法

    void CreateListF(LinkList& L, int n)
    {
    
        LinkList pre;
        L = new LNode;
        L->next = NULL;
        ElemType i;
        for ( i = 0; i < n; i++)
        {
    
            pre = new LNode;
            cin >> pre->data;
            pre->next = L->next;
            L->next = pre;
        }
    }
    
    

    图解:

    · 有序单链表插入删除

    (1)插入数据

    void ListInsert(LinkList& L, ElemType e)
    {
    	LinkList p,pre;
    	p = new LNode;
    	p->data = e;
    	pre = L;
    	while (pre->next)
    	{
    		if (pre->next->data > e)//找到第一个比要插入数据大的数
    		{
    			p->next = pre->next;
    			pre->next = p;
    			return;
    		}
    		else pre = pre->next;
    	}
    	p->next = pre->next;//若插入数据最大则插在最后
            pre->next = p;
    }
    	
    

    (2)删除数据

    
    void ListDelete(LinkList& L, ElemType e)
    {
    	if (L->next == NULL)return;
    	LinkList p, pre;
    	pre = L;
    	while (pre->next)
    	{
    		if (pre->next->data == e)//遍历链表找到要删除目标位置
    		{
    			p = pre->next;
    			pre->next = p->next;
    			delete p; return;
    		}
    		else pre = pre->next;
    	}
    	cout <<e<< "找不到!"<<endl;//删除要考虑找不到的情况
    }
    
    

    · 合并两个单链表

    
    void MergeList(LinkList& L1, LinkList L2)//合并链表,使合并后的链表非降排列
    {
    	LinkList p = L1->next, q = L2->next, L3, r, node;
    	r = new LNode;
    	r->next = NULL;
    	L3 = r;
    	while (p && q)//同时遍历
    	{
    		if (p->data > q->data)
    		{
    			node = q;
    			q = q->next;//指针下移
    			node->next = NULL;
    			r->next = node;
    			r = node;
    		}
    		else if (p->data < q->data)
    		{
    			node = p;
    			p = p->next;//指针后移
    			node->next = NULL;
    			r->next = node;
    			r = node;
    		}
    		else
    		{
    			node = p;
    			q = q->next;
    			p = p->next;//两个指针同时后移
    			node->next = NULL;
    			r->next = node;
    			r = node;
    		}
    	}
    	if (p)r->next = p;
    	if (q)r->next = q;
    	L1 = L3;
    }
    
    

    · 循环链表


    对于循环链表这种设计,我们在遍历的时候的结束条件就不再是p为空的时候结束了。而是!!p等于头结点!!的时候遍历才完成。

    · 双向链表


    1.2学习体会

    顺序表还好,链表要特别小心p和p->next是否为空,还有其他的next关系,学习链表要从基础的开始,先把链表建好,熟悉头插和尾插,在掌握其他操作如插入,删除,逆序,合并等,此外还可以了解一些C++对于链表常用的库函数,如vector和algorithm里的一些和顺序表操作有关的函数。

    2.PTA实验作业

    2.1 题目:6-11 链表分割

    2.1.1 代码截图

    2.1.2 PTA提交列表及说明


    2.2题目:6-8 链表倒数第m个数

    2.2.1 代码截图

    2.2.2 PTA提交列表及说明


    2.3题目:7-1 两个有序序列的中位数、

    2.3.1 代码截图

    2.3.2 PTA提交列表及说明


    3.阅读代码

    3.1

    问题:

    代码如下:
    法一:

    
    
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int N,W;
    const int maxn=105;
    int v[maxn],w[maxn];
    int rec(int i,int j)//从第i个下标开始,计算剩余j重量怎么挑选商品 
    {
        int ans;
        if(i==N) ans=0;//已经没有商品可以选择,递归出口。
        else if(j<w[i]) ans=rec(i+1,j);//如果背包容量装不下下标为i的商品 
        else ans=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);/*方程由来:http://blog.sina.com.cn/s/blog_e65dd0270102wd9k.html*/
        return ans;
    }
    int main()
    {
        cin>>N>>W;
        for(int i=0;i<N;i++) cin>>w[i];
        for(int i=0;i<N;i++) cin>>v[i];
        int res=rec(0,W);
        cout<<res<<endl;
        return 0;
    }
    
    
    

    这种算法是对每个商品都进行处理,每一层搜索都有两个分支,时间复杂度为O(2^n),当n比较大的时候就会花费较多的时间。
    对每个商品进行搜索的时候,有时会出现相同的参数,于是第二次调用的时候我们其实已经计算过一次了,等于是白白浪费了时间。

    ···

    法二:

    
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxN=3405;
    const int maxW=405;
    int dp[maxN][maxW];
    int N,W;
    int w[maxW],v[maxN];
    int rec(int i,int j){    
         if(dp[i][j]>=0) return dp[i][j];
         int ans;
         if(i==N) ans=0;
         else if(j<w[i]) ans=rec(i+1,j);
         else ans=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
         return dp[i][j]=ans;
     }
     int main(){
         memset(dp,-1,sizeof(dp));
         cin>>N>>W;
         for(int i=0;i<N;i++)
         {
             cin>>w[i];
             cin>>v[i];
         }
         int res=rec(0,W);
         cout<<res<<endl;
         return 0;
     }
    
    
    

    dp[][]为记忆数组,用于记录下之前每一次的结果。我们如果把dp[i][j]定义成如下意义:当总重量小于j时,从下标为i的商品开始挑选,得到商品的最大值。于是有下面的递推公式:

    法三:

    
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxN=3405;
    const int maxW=405;
    int dp[maxN][maxW];
    int N,W;
    int w[maxW],v[maxN];
    void  solve(){    
         for(int i=N-1;i>=0;i--){
             for(int j=0;j<=W;j++){
                if(j<w[i]) 
                     dp[i][j]=dp[i+1][j];
                 else 
                     dp[i][j]=max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
             }
         }
             
         cout<<dp[0][W]<<endl;
    }
     int main()
    {
         cin>>N>>W;
         for(int i=0;i<N;i++)
         {
             cin>>w[i];
             cin>>v[i];
         }
         solve();
         return 0;
    }
    
    
    
  • 相关阅读:
    【华为云技术分享】手把手教你如何在ARM上源码编译Redis
    【华为云技术分享】Linux内核编程环境 (2)
    华为云MySQL 8.0正式商用,全新增强版开源利器强势来袭
    【转载】Mysql删除所有表不删除数据库方法
    【转载】使用Sublime Text 3的HTML-CSS-JS Prettify插件格式化代码
    【转载】Node.js学习笔记之一
    jquery分页插件pagination.js的使用
    Windows平台下搭建Git服务器
    js实现返回页面顶部
    交换机的级联和堆叠
  • 原文地址:https://www.cnblogs.com/19wangluo-Lishaoqiang/p/12445313.html
Copyright © 2020-2023  润新知