# 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;//指向后继结点



### · 两种建立链表的方式

#### (1)尾插法

void CreateList(LinkList& L, int n)
{
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)
{

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)
{
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)删除数据


{
if (L->next == NULL)return;
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;//删除要考虑找不到的情况
}



### · 合并两个单链表


{
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;
}



# 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;
}



···


#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;
}


posted @ 2020-03-08 22:52  一个敢敢  阅读(235)  评论(0编辑  收藏  举报