线性表部分习题

关键字
- 递增有序链表
- 不允许有重复的数据
- 保持递增关系(使用后插法)
- 不占用额外的空间(额外的新建结点维持逻辑)
思路
- a.待合并链表La,Lb,头指针Lc; 借用La的头结点
- b.定义pa,pb指针
- c.循环(La,Lb都没有达到尾结点的位置)
- d.判断链表取较小者,存储Lc
- e.相等La元素插入Lc,Lb释放掉
void MergeList(LinkList *La,LinkList *Lb,LinkList *Lc){
LinkList pa,pb,pc,temp;
pa = (*La)->next;
pb = (*Lb)->next;
*Lc = *La;
pc = *La;
while(pa && pb){
if(pa->data < pb.data){
pc->next = pa;
pc = pa;
pa = pa->next;
}else if(pa->data > pb->data){
pc->next = pb;
pc = pb;
pb = pb ->next;
}else{
pc ->next = pa;
pc = pa;
temp = pb->next;
free(pb);
pb = temp;
}
}
pc ->next = pa ? pa : pb ;
free(*Lb);
}
解析
- 1.La,Lb,Lc(Lc指向La的头结点)
- 2.pa,pb,首元结点
- 3.循环条件 pa,pb不为空
- 4.相等的话 La结点链接到Lc上 同时释放Lb结点
- 5.较小的话 释放
- 6.释放掉未走到的结点

void Intersection(LinkList *La,LinkList *Lb,LinkList *Lc){
LinkList pa,pb,pc,temp;
pa = (*La)->next;
pb = (*Lb)->next;
*Lc = pc = *La;
while(pa && pb){
if(pa->data == pb->data){
pc->next = pa;
pc = pa;
pa = pa->next;
temp = pb;
pb = pb->next;
free(temp);
}else if(pa->data < pb->data){
temp = pa;
pa = pa->next;
free(temp);
}else{
temp = pb;
pb = pb->next;
free(temp);
}
}
while(pa){
temp = pa;
pa = pa->next;
free(temp);
}
while(pb){
temp = pb;
pb = pb->next;
free(temp);
}
pc->next = NULL;
}
关键词
解析
- a. *L 作为新的旋转后的链表的首节点
- b. p指针指向首元结点
- c. 从前往后遍历链表 临时变量q指向待插入结点的后继结点
使用头插法
void Inverse(LinkList *L){
LinkList p,q;
p = (*L)->next;
(*L)->next = NULL;
while(p){
q = p->next;
p->next = (*L)->next;
(*L)->next = p;
p = q;
}
}
关键词
- a 遍历链表 第一个大于minK结点,pre 保存前驱
- b 遍历链表 第一个大于maxK结点, p指向;
- c 修改pre->next = p
- d 释放介于pre和p之间的结点
解析
void DeleteMinMax(LinkList *L,int mink,int maxk){
LinkList p,q,pre,temp;
pre = *L;
p = (*L)->next;
while(p && p->data < mink){
pre = p;
p = p->next;
}
while(p && p->data <= maxk){
p=p->next;
}
q = pre->next;
pre->next = p;
while(q !=p){
temp = q->next;
free(q);
q = temp ;
}
}
思路
- a n个数据原地逆置 9 8 7 6 5 4 3 2 1 0
- b 拆解【9 8 7 6 5 4 3】【2 1 0】
- n-p个数据和p个数据再一次逆置 【3 4 5 6 7 8 9】【0 1 2】
void Reverse(int *pre,int left,int right){
int i = left , j= right;
int temp;
while(i<j){
temp = pre[i];
pre[i] = pre[j];
pre[j] = temp;
i++;j--;
}
}
void LeftShift(int *pre,int n,int p){
if(p>0 && p<n){
Reverse(pre,0,n-1);
Reverse(pre,0,n-p-1);
Reverse(pre,n-p,n-1);
}
}
分析
思路
- 选择候选主元素,循环技术方式找到链表那个元素出现次数最多,认为候选人
- 循环目的:候选人到底出现了多少次
- 判断是不是候选人 count > n/2
int MainElement(int *A,int n){
int count =1;
int key = A[0];
for(int i=1;i<n;i++){
if(A[i]== key){
count ++;
}else{
if(count > 0 ){
count --;
}else{
key = A[i];
count = 1;
}
}
}
if(count > 0){
for(int i= count=0;i<n;i++){
if(A[i] == key){
count++;
}
}
}
if(count > n/2){
return key;
}
return -1;
}
关键词
解析
- 1 申请n+1个辅助空间数组t,赋初始值为0;
- 2 首元结点开始遍历,t[|data|] 保留结点 t[|data|] = 1;若t[|data|] =1 就删除;
void DeleteEqualNode(LinkeList *L,int n){
int *p = alloca(sizeof(int)*n);
LinkList r = *L;
for(int i= 0;i < n;i++){
*(p+i) = 0;
}
LinkList temp = (*L)->next;
while(temp != NULL){
if(p[abs(temp->data)] == 1){
r->next = temp ->next;
free(temp);
temp = r->next;
}else{
p[abs(temp->data)] = 1;
r = temp;
temp = temp->next;
}
}
}