知识点总结报告
知识点:
链表
(原理)每个存储结点含有数据域和指针域。线性表中每个元素只有一个前驱结点和一个后续元素。链表分为单链表,双链表。
单链表
每个结点类型声明
typedef struct LNode
{ ElemType data; //存放元素值
struct LNode *next; //指向后继节点
}LinkNode; //单链表结点类型
插入结点 s->next=p->next; p->next=s;
删除结点 q=p->next; //q临时保存被删结点 p->next=q->next; //从链表中删除结点q free(q); //释放结点q的空间
建立单链表
1)头插法
void CreateListF(LinkNode *&L,ElemType a[ ],int n)
{ LinkNode *s;
L=(LinkNode *)malloc(sizeof(LinkNode));
L->next=NULL; //创建头结点,其next域置为NULL
for(int i=0;i<n;i++) //循环建立数据结点s
{ s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=a[i]; //创建数据结点s
s->next=L->next; //将结点s插入到原首结点之前,头结点之后
L->next=s;
}
}
2)尾插法
void CreateListR(LinkNode *&L,ElemType a[ ],int n)
{ LinkNode *s,*r;
L=(LinkNode *)malloc(sizeof(LinkNode)); //创建头节点
r=L; //r始终指向尾结点,初始时指向头结点
for(int i=0;i<n;i++) //循环建立数据结点s
{ s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=a[i]; //创建数据结点s
r->next=s; //将结点s插入到结点r之后
r=s;
}
r->next=NULL; //尾结点的next域置为NULL
}
初始化线性表InitList(&L)
void InitList(LinkNode *&L)
{ L=(LinkNode *)malloc(sizeof(LinkNode));
L->next= NULL; //创建头结点,其next域置为NULL
}
销毁线性表DestroyList(&L)
void DestroyList(LinkNode *&L)
{ LinkNode *pre=L,*p=L->next; //pre指向结点p的前驱结点
while(p!=NILL) //扫描单链表L
{ free(pre); //释放pre结点
pre=p; //pre.p同步后移一个结点
p=pre->next;
}
free(pre); //循环结束时p为NULL,pre指向尾结点,释放它
}
判断线性表是否为空表ListEmpty(L)
bool ListEmpty(LinkNode *L)
{ return(L->next==NULL);
}
求线性表的长度ListLength(L)
int ListLength(LinkNode *L)
{ int n=0;
LinkNode *p=L; //p指向头结点,n置为0(即头结点的序号为0)
wile(p->next!=NULL)
{ n++;
p=p->next;
} //循环结束时,p指向尾结点,其序号n为结点个数
return(n);
}
输出线性表DispList(L)
void DispList(LinkNode *L)
{ LinkNode *p=L->next; //p指向首结点
while(p!=NULL)
{ printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
求线性表中的某个数据元素值GetElem(L,i,&e)
bool GetElem(LinkNode *L,int i,ElemType &e)
{ int j=0;
LinkNode *p=L; //p指向头结点,j置为0(即头结点的序号为0)
if(i<=0)return false; //i错误返回假
while(j<i&&p!=NULL) //找第i个结点p
{ j++;
p=p->next;
}
if(p==NULL) //不存在第i个数据结点,返回false
return false;
else //存在第i个结点,返回true
{ e=p->data;
return true;
}
}
按元素值查找LocateElem(L,e)
int LocateElem(LinkNode *L,Elemtype e)
{ int i=1;
LinkNode *p=L->next; //p指向首结点,i置为1(首结点序号为1)
while(p!=NULL&&p->data!=e) //查找data值为e的结点,序号为i
{ p=p->next;
i++;
}
if(p==NULL) //不存在值为e的结点,返回0
return(0);
else //存在值为e的结点,返回逻辑序号i
return(i);
}
插入数据元素ListInsert(&L,i,e)
bool ListInsert(LinkNode *&L,int i,ElemType e)
{ int j=0;
LinkNode *p=L,*s; //p指向头结点,j置为0(头结点序号为0)
if(i<=0) return false; //i错误返回false
while(j<i-1&&p!=NULL) //查找第i-1个结点p
{ j++;
p=p->next;
}
if(p==NULL) //未找到第i-1个结点,返回false
return false;
else //找到第i-1个结点p,插入新结点并返回true
{ s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=e; //创建新结点s,其data域置为e
s->next=p->next; //将结点s插入到结点p之后
p->next=s;
rerturn true;
}
}
删除数据元素ListDelete(&L,i,&e)
bool ListDelete(LinkNode *&L,int i,ElemType &e)
{ int j=0;
LinkNode *p=L,*q; //p指向头结点,j置为0(头结点序号为0)
if(i<=0) return false; //i错误返回false
while(j<i-1&&p!=NULL) //查找第i-1个结点
{ j++;
p=p->next;
}
if(p==NULL) //未找到第i-1个结点,返回false
return false;
else //找到第i-1个结点p
{ q=p->next; //q指向第i个结点
if(q==NULL) //若不存在第i个结点,返回false
return false;
e=q->data;
p->next=q->next; //从单链表中删除q结点
free(q); //释放q结点
return true; //返回true表示成功删除第i个结点
}
}
(例题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1216
The first contestant in the queue was asked for his number (which was 2). He was freed from the washing up and could party on, but every second contestant behind him had to go to the kitchen (those with numbers 4, 6, 8, etc). Then the next contestant in the remaining queue had to tell his number. He answered 3 and was freed from assisting, but every third contestant behind him was to help (those with numbers 9, 15, 21, etc). The next in the remaining queue had number 5 and was free, but every fifth contestant behind him was selected (those with numbers 19, 35, 49, etc). The next had number 7 and was free, but every seventh behind him had to assist, and so on.
Let us call the number of a contestant who does not need to assist with washing up a lucky number. Continuing the selection scheme, the lucky numbers are the ordered sequence 2, 3, 5, 7, 11, 13, 17, etc. Find out the lucky numbers to be prepared for the next contest party.
题目分析:
开始有很多人从2开始编号,依次为2,3,4,5,6.。。。
每次删除元素,从第一个开始删, 2,那么每隔2个删除那个元素,,于是删除了 4,6,8,10, 现在数组变成 2,3,5,7,9,11,13,15,17,19,21。。
然后从3开始删除 ,每隔3个删除删除元素 ,,于是删除了9,15,21, 现在变成 2,3,5,7,11,13,17,19...
然后从5开始删除每隔5个删除一个 于是删除了 19,35,49。根据题目的数据范围,只要求到第3000个数就行。
题解代码:
#include<stdio.h> #include<string.h> #define M 34000 int n,num[M],ss[3001],t=0; int main() { int i,j,k; memset(num,0,sizeof(num)); for(i=2;i<M;i++) { if(!num[i]) { ss[t++]=i;k=0; for(j=i+1;j<M;j++) if(!num[j]) { k++; if(k==i) { k=0; num[j]=1; } } } if(t==3000) {break;} } while(scanf("%d",&n),n!=0) { printf("%d\n",ss[n-1]); } return 0; }
---恢复内容结束---