【练习回顾】DS前三次作业
第一次作业
T2.基本计算器
使用了数组栈——数字栈和符号栈
T5.全排列输出(permutation)
使用了标准写法——字典序算法
void reverse(int left,int right);/*逆转a[left]~a[right]顺序*/
int nextPermutation(int n)/*1~n的全排列*/
{
int i,j;
for(i=n-1;i>0 && a[i]<a[i-1];i--); //从后向前,找到当前排列中首个a[i-1]<a[i](升序)的位置——即子列峰值
if(i==0) return 0;
else
{ //从a[i]开始向后,找到子排列中首个比a[i-1]小的a[j],这样a[j-1]就是最小的比a[i-1]大的数,是a[i-1]下一个全排列的目标值(我们就是这么想的)
//于是交换a[i-1]和a[j-1]的值,再将其后的子列逆序以期得到极小的排列增长(其实就有递归的思想)
for(j=i;j<n && a[j]>a[i-1];j++);
a[j-1]^=a[i-1],a[i-1]^=a[j-1],a[j-1]^=a[i-1];
reverse(i,n-1);
return 1;
}
}
/*主体操作,a[0]~a[n-1]全排列输出*/
do{
for(i=0;i<n;i++) printf("%d ",a[i]);
puts(""); //输出
}while(nextPermutation(n)); //得到下一个排列
return 0;
e.g.
1 3 5 4 2
1 3 5 4 2 a[i-1]=3 从后向前首个升序处,也是下一个排列的目标更改出
1 3 5 4 2 a[j-1]=4 大于a[i-1]的极小值
1 4 5 3 2 此后子列必倒序逆序排列即可
1 4 2 3 5 < FINAL
第二次作业
选填
关于优先级:
[] , () , . , -> | * , & ,++/-- |
---|---|
从左向右 1 | 从右向左 2 |
一些可移植性差的函数警惕
feof()
fflush()
第三次作业
T3.链表存储多项式时,野指针读入的错误及其衍生错误
typedef struct node
{
int coef;
int exp;
struct node *link;
} PNode, *PLinklist; /*链表形式*/
PLinklist readPoly() /*读入多项式*/
{
PLinklist list=NULL;
//应为想用作接口,使用了局部的变量list来普遍化操作,结果忘记赋值成了野指针,在配合上本地CodeBlocks编译器的环境优化,产生了千奇百怪的错误结果
PLinklist p,r;
do
{
p=(PLinklist)malloc(sizeof(PNode));
scanf("%d%d",&p->coef,&p->exp);
p->link=NULL;
if(list==NULL) list=p; //若为野指针,此处list==NULL就挂了
else r->link=p;
r=p;
}while(getchar()!='\n');//当检测到行末'\n'后结束
return list;
}
此次大失误让人进一步了解了自己编译器的尿性(猜测):
咱的编译器会给野指针沿用之前历史的值,若没有历史则赋为NULL;
然后如果中间有些扰动(在其他域申明了相同名字的变量时)就会丢弃历史值。
因而两个链表连缀起来了
然而有些错误尚无法解释,需进一步研究:
加入printf("sf");
后只读入前半,直接爆炸
加入printf("sf\n");
就不会如此
T1.多线段连缀,找最长连续线段
由于数据点弱,感觉什么算法都能过,但自己竟然卡了那么久;
使用了自创的想法:单链表表示线段,单循环链表记录每条线段的头结点(方便顺次循环比较)
因为忽视了循环链表表头丢失的可能性
typedef struct node
{ /* 记录一条连续线段*/
int x;
int y;
struct node *link;
} LNode, *Line;
typedef struct circleHead
{
Line head; /* 记录每个连续线段头结点*/
int num; /* 记录该连续线段的组成线段数*/
struct circleHead *link;
} CNode, *hCoord;
int doConnect(int last) //还是无脑的循环比较,直至线段集合不再变动
{
int i=0;
hCoord p=Clist,q,pre;
Line pp,rr;
while(i<last)
{
pp=p->head;
while(pp->link!=NULL) pp=pp->link;
rr=pp;
for(q=p->link,pre=p;q!=p;pre=q,q=q->link)
{
if(isConnect(q->head,rr))
{
rr->link=q->head->link;
p->num+=q->num;
pre->link=q->link;
last--;
i=0;//清零,否则会有跳过的可能性(好傻!)
break;
}
}
if(q==p) i++;
else
{
free(q);
continue;
}
p=p->link;
Clist=p; /* 注意当p不是Clist时,可能会因为Clist所指的结点移动到p结点后而导致Clist丢失*/
}
return last;
}
此题助教推荐了并查集,学学去