逆置问题:
例1:
1、将一长度为n的数组的前端K(k<n)个元素逆序后移动到数组后段,要求原数组总数据不丢失。
2、将一长度为n的数组的前端K(k<n)个元素保持原序后移动到数组后段,要求原数组总数据不丢失。
3、将数组中的元素循环左移p(0<p<n)个位置。
1 2 3 4 5 6 7 8 9 10 11
| void reverse(int a[],int left,int right,int k) { int temp; for (int i=left,j=right;i<left+k && i<j;++i,--j) { temp=a[i]; a[i]=a[j]; a[j]=temp;
} }
|
1 2 3 4 5
| void moveToEnd(int a [],int n ,int k) { reverse(a,0,k-1,k); reverse(a,0,n-1,k); }
|
1 2 3 4 5 6
| void moveP(int a [],int n,int p) { reverse(a,0,p-1,p); reverse(a,p,n-1,n-p); reverse(a,0,n-1,n); }
|
最值问题:
1:在线性表中找最值
1 2 3 4 5 6 7 8 9 10
| int max=a[0]; int maxIdx=0; for(int i=0;i<n;++i) { if (max<a[i]) { max=a[i]; maxIdx=i; } }
|
这个是最大值,最小值同理。
2:在链表中找最小值:
1 2 3 4 5 6 7 8 9 10 11 12
| LNode *p,*q; int min=head->next->data; q=p=head->next; while(p!=NULL) { if(min>p->data) { min=p->data; q=p; } p=p->data; }
|
在链表中找最大值同理。
例:一双链表非空,有head指针指出,结点结构为{llink,data,rlink},请设计一个将结点数据域data值最大的那个结点(最大值结点只有一个)移动到链表最前边的算法,要求不得申请新结点空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| void maxFirst(DLNode *head) { DLNode *p=head->rlink,*q=p; int max=p->data;
while(p!=NULL) { if(max<p->data) { max=p->data; q=p; } p=p->rlink; }
DLNode *l=q->llink; *r=q->rlink; l->rlink=r; if(r!=NULL) r->llink=l;
q->llink=head; q->rlink=head->rlink; head->rlink=q; q->rlink->llink=q; }
|
归并问题:
1:顺序表归并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void mergearray(int a [],int m,int b[],int n,int c[]) { int i=0,j=0; int k=0; while(i<m&&j<n) { if(a[i]<b[j]) c[k++]=a[i++]; else c[k++]=b[j++]; } while(i<m) c[k++]=a[i++]; while(j<n) c[k++]=b[j++]; }
|
分别将a[]和b[]的数组有小到大的归并为数组c[],m,n分别为两个数组的长度,c数组的长度为两个长度的之和,所以不需要再来一个变量来存储了。i,j分别是数组下标用来指出哪个元素在进行比较,k是指向c数组的下标。如果a[i]<b[j]则将a[i]赋值给c[k],且k向后移一位,i也向后移一位。下一个while是在一个数组全部比较完而另一个数组还有剩余的时候,将剩余的数组中的每一个元素都移动到数组c中去。
2:链表归并
–顺序归并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| void merge(LNode *A,LNode *B,LNode *&C) { LNode *p=A->next; LNode *q=B->next; LNode *r; C=A; C->next=NULL; free(B); r=C; while(p!=NULL&&q!=NULL) { if(p->data<=q->data) { r->next=p; p=p->next; r=r->next; } else { r->next=q; q=q->next; r=r->next; } if(p!=NULL) r->next=p; if(q!=NULL) r->next=q; }
}
|
p,q是指向两个链表的指针,C是指向新链表的指针,r是指向新链表表尾的指针。C=A是以A链表的头结点作为新链表的头结点。然后释放B结点(头结点)。此时新链表为空链表,所以r指针指向此时的头结点r=C。
–逆序归并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| void mergeR(LNode *A,LNode *B,LNode *&C) { LNode *p=A->next; LNode *q=B->next; LNode *s; C=A; C->next=NULL; free(B); while(p!=NULL&&q!=NULL) { if(p->data<=q->data) { s=p; p=p->next; s->next=C->next; C->next=s; } else { s=q; q=q->next; s->nexr=C->next; c->next=s; } while(p!=NULL) { s=p; p=p->next; s->next=C->next; C->next=s; } while(q!=NULL) { s=q; q=q->next; s->next=C->next; C->next=s; } }
}
|
用头插法的形式重新进行归并,这样就得到了逆序。在一个链表的元素全部取完之后,逆序的话剩余的元素就不能直接修改指针了,要用循环将剩余的元素一个一个的以头插法的形式插入到新链表中。
划分问题:
取什么数作为树轴,这个数的大小是关键,这个数的由来不是关键。
1:以数组中的第一个元素为树轴,左边的元素为小于树轴的元素,右边的元素为大于树轴的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| void partition(int arr[],int n) { int temp; int i=0;j=n-1; temp=arr[i]; while(i<j) { while(i<j&&arr[j]>=temp) --j; if(i<j) { arr[i]=arr[j]; ++i; } while(i<j&&arr[i]<temp) ++i; if(i<j) { arr[j]=arr[i]; --j;
} } arr[i]=temp; }
|
2:以任意一个数作为树轴,左边的元素为小于树轴的元素,右边的元素为大于树轴的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| void partition(int arr[],int n,int comp) { int temp; int i=0;j=n-1; temp=arr[i]; while(i<j) { while(i<j&&arr[j]>=comp) --j; if(i<j) { arr[i]=arr[j]; ++i; } while(i<j&&arr[i]<comp) ++i; if(i<j) { arr[j]=arr[i]; --j;
} } arr[i]=temp; }
|
这里i和j共同指向的还是temp,comp只是一个比较大小的标准,comp都不一定是数组中存在的元素。理解最前面的黑体字就懂这个类型了。
3:以数组元素中的任意一个元素作为树轴,左边小于树轴,右边大于树轴。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| void partition(int arr[],int n ,int k) { int temp; int i=0;j=n-1; temp=arr[0]; arr[0]=arr[k]; arr[k]=temp; temp=arr[i]; while(i<j) { while(i<j&&arr[j]>=temp) --j; if(i<j) { arr[i]=arr[j]; ++i; } while(i<j&&arr[i]<temp) ++i; if(i<j) { arr[j]=arr[i]; --j;
} } arr[i]=temp; }
|
将这个数组中k位置的值直接放在数组中的第一个位置那就行。之所以放在第一个那,只是后面的代码和第一种情况的一个统一,更方便的去操作。