数据结构线性表部分习题(一)
最近有考研的打算,准备考研科目,先是数据结构部分。习题如下;
1、求从大到小排序的L1,L2,L3交集(其中可能有多个相同元素在里面),最终结果也要按照从大到小的顺序排列,且不允许有重复值!!!
Linklist Interaction(Linklist L1,Linklist L2,Linklist L3){
node *p = L1->next;
node *q = L2->next;
node *r = L3->next;
L1->next=NULL; #条件是求L1,使其包含三个表的交集,所以保留L1的结构
free(L2);
free(L3);
while(p&&q&&r){
node *tep;
#node *t;
if(p->data == q->data == r->data)#都相等把元素插入到L1中,然后三个表都做后移操作,进行下一轮比较
{
tem = p;
p = p->next;
tem->next = L1->next;
L1->next = tem;#此法为前插法,后插法的操作是加一个指针t,移动t的位置进行插入,上述的让t=L1,然后把L1换成t,
tem = q;#在这一步前面加上t=tem操作就可实现后插操作
q = q->next;
free(tem);
tem = r;
r = r->next;
free(tem);
}
if(p->data <= q->data&&p->data <= r->data)
{
tem = p;
p = p->next;
free(tem);
}
elif(q->data <= p->data&&q->data <= r->data)
{
tem = q;
q = q->next;
free(tem);
}
else
{
tem = r;
r = r->next;
free(tem);
}
while(p){#到这一步说明有一个表已经到最后了,这样其他的表里面剩余的元素就没有共同的了,全部删除就可
tem = p;
p = p->next;
free(tem);
}
while(q){
tem = q;
q = q->next;
free(tem);
}
while(r){
tem = r;
r = r->next;
free(tem);
}
return L1;
}
}
#总结一下
###三个表的元素一起拿出来比大小,最小的往后推一位,
####如果都相等就把元素插入(前插法)L1中(要是题目要求最后目标也是有顺序的话,可以进行后插法的操作
2、已知L为链表的头结点地址,表中共有m(m>3)个结点,从表中第i个结点l
个结点构成一个循环部分链表,设计将这部分循环链表中所有结点顺序完全倒置的算法。
void Reverse(Linklist h){
node *p = h->next;
h->next = NULL;
while(p){
node *q = p;
p = p->next;
q->next = h->next;
h->next = q;
}
}
void Cicular_Reverse(lisklist head, int i, int m){
node *pi,*pm,*p = head;
for(int j = 0; j<m ;++j){
p = p->next; //一直循环后移,知道j=i-1,这时候p指向第i-1个元素,赋值给pi
if(j = i-1){
pi = p;
}
}
p = p->next; //出循环后p指向第m-1个元素在后移一个到最后一个元素m上
pm = p;
p = pi;
pi = pi->next; //此时p指向i的前驱,pi指向i ,pm指向最后一个元素m
Reverse(p); //把p后面所有元素逆置,就是相当于把p做头节点,p后面一个元素做首元结点也就是pi(i元素)
pi->next = pm;
}
3、
设有一个由正整数组成的无序单链表,编写算法实现下列功能:
(1) 找出最小值结点,且显示该数值。
(2) 若该数值为奇数,则将其与直接后继结点的数值交换。
(3) 若为偶数,则将其直接后继结点删除。
void outmin(LinkList L)
{
LinkList p=L,q=L;
int temp;
while(q)
{
if(p.data>q.data)
{
p=q;
}
q=q.next;
}
printf("%d",p.data);
if(p.next)
{
if(p.data%2==1)
{
temp=p.data;p.data=p.next.data;p.next.data=temp;
}
else
{
q=p.next;p.next=q.next;free(q);
}
}
}
4、L1,和L2分别为两个单链表头结点地址指针,且两个表中数据结点的数据域均为一个字母(见图1-1-5),设计一个空间复杂度为0(1)且时间上尽可能高效的算法,把L与L中相同的一段链结点顺序完全倒置(一个结点最多倒置一次)。

typedef struct node{
char data;
struct node *next;
}node,Linklist;
linklist a,b;
void Reverse(Linklist h, Linklish q){
node *p = h->next;
h->next = q; //指向最后一个元素,相当于头插逆置
while(p!=q){
node *tem = p;
p = p->next;
tem->next = h->next;
h->next = tem;
}
}
void Substr_Reverse(Linklist L1, Linklist L2){
if(!L1->next ||!L2->next){//有一个为空就退出
return;
}
node *start = L1, *p = start->next, *q = L2->next; //p指向L1第一个元素,q指向L2的第一个元素
while(p){
while(p&&q&&p-data == q->data){ //让q和p进行模式比较
p = p->next;
q = q->next;
}
if(!q){ //执行这一步模式匹配完,进行逆置操作
Reverse(start,p); //逆置说明q的所有元素在p某一段,那就从头逆置
start = p; //从匹配成功的后一个元素开始匹配下一次,q还是从头来
p = start->next;
q = L2->next;
}
else if(!p){ //目标串匹配完,直接结束
break;
}
else{ // 匹配失败 ,p从第二个元素开始,q还是从第一个元素开始匹配
start = start->next;
p = start->next;
q = L2->next;
}
}
}