1.单链表的基本操作
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
LinkList List_HeadInsert(LinkList &L)
{
LNode *s;
int x;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
scanf("%d",&x);
while(x!=9999)
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d",&x);
}
return L;
}
LinkList List_TailInsert(LinkList &L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s,*r=L;
int x;
scanf("%d",&x);
while(x!=9999)
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d",&x);
}
r->next = NULL;
return L;
}
LNode *GetElem(LinkList L, int i)
{
int j = 1;
LNode *p = L->next;
if(i==0)
return L;
if(i<1)
return NULL;
while(p&&j<i)
{
p=p->next;
j++;
}
return p;
}
LNode *LocationElem(LinkList L,ElemType e)
{
LNode *p = L->next;
while(p&&p->data!=e)
{
p = p->next;
}
return p;
}
int getLength(LinkList L)
{
int length = 0;
LNode *p =L->next;
while(p)
{
p = p->next;
length++;
}
return length;
}
void printLinkList(LinkList L)
{
LNode *p = L->next;
while(p)
{
printf("%d ",p->data);
p = p->next;
}
putchar('\n');
}
2.在带头结点的单链表L中,删除所有值为x的结点,并释放空间,假设值为x的结点不唯一,试编写算法以实现上述操作。
void Del_X(LinkList &L,ElemType x)
{
LNode *p,*pre,*r;
pre = L;
p = L->next;
while(p!=NULL)
{
if(p->data == x)
{
r = p->next;
pre->next = p->next;
free(p);
p = r;
}
else
{
pre = p;
p = p->next;
}
}
}
3.设L为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。
void reverse_print(LinkList L)
{
LinkList L2 = (LinkList)malloc(sizeof(LNode));
LNode *p = L->next,*q;
while(p)
{
q = (LNode *)malloc(sizeof(LNode));
q->data = p->data;
q->next = L2->next;
L2->next = q;
p = p->next;
}
printLinkList(L2);
}
4.试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)。
void Del_Min(LinkList &L)
{
LNode *p,*q,*pre = L;
p = L->next;
int min = p->data;
while(p)
{
if(p->data < min)
{
min = p->data;
}
p = p->next;
}
p = L->next;
while(p && p->data != min)
{
pre = p;
p = p->next;
}
q = p;
pre->next = p->next;
free(q);
}
5.试编写算法将带头结点的单链表就地逆置,所谓"就地"是指辅助空间复杂度为O(1)。
void Reverse_LinkList(LinkList &L)
{
LNode *p = L->next,*r;
L->next = NULL;
while(p)
{
r = p->next;
p->next = L->next;
L->next = p;
p =r;
}
}
6.有一个带头结点的单链表L,设计一个算法使其元素递增有序。
void sortList(LinkList &L)
{
int length = getLength(L);
LinkList L2 = (LinkList)malloc(sizeof(LNode));
LNode *p = L->next,*pre = L,*max = L->next,*maxpre = L;
L2->next = NULL;
while(length > 0)
{
while(p != NULL)
{
if(p->data > max->data)
{
max = p;
maxpre = pre;
}
pre = p;
p = p->next;
}
maxpre->next = max->next;
max->next = L2->next;
L2->next = max;
length--;
p = L->next;
max = L->next;
maxpre = L;
pre = L;
}
L = L2;
}
7.设在一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素(若存在)。
void Del_BetweenMN(LinkList &L, int m, int n)
{
LNode *p = L->next,*pre = L,*r;
while(p!=NULL)
{
if(p->data <= n && p->data >= m)
{
r = p->next;
pre->next = p->next;
free(p);
p = r;
}
else
{
pre = p;
p = p->next;
}
}
}
8.给定两个单链表,编写算法找出两个链表的公共结点。
LNode getCommon(LinkList LA,LinkList LB)
{
int lengthA = getLength(LA);
int lengthB = getLength(LB);
int k;
LNode *p,*q;
if(lengthA >= lengthB)
{
p= LA->next;
q = LB->next;
k = lengthA -lengthB;
}
else
{
p= LB->next;
q = LA->next;
k = lengthB -lengthA
}
while(k--)
p = p->next;
while(p)
{
if(p==q)
return p;
else
{
p = p->next;
q = q->next;
}
}
return NULL;
}
9.给定一个带头结点的单链表,设head为头指针,结点结构为(data,next),data为整型元素,next为指针,试写算法按递增次序输出单链表中各节点的数据元素,并释放结点所占的内存空间(要求:不允许使用数组作为辅助空间)。
void sortList2(LinkList &L)
{
LNode *p = L->next,*minp = L->next,*pre = L, *minpre = L;
LinkList L2;
L2 = (LinkList)malloc(sizeof(LNode));
LNode *r =L2;
int length = getLength(L);
while(length > 0)
{
while(p!=NULL)
{
if(p->data < minp->data)
{
minp = p;
minpre = pre;
}
else
{
pre = p;
p = p->next;
}
}
r->next = minp;
r = minp;
minpre->next = minp->next;
minp->next = NULL;
length--;
p = L->next;
minp =L->next;
pre = L;
minpre = L;
}
r->next = NULL;
p = L2->next;
while(p)
{
r = p->next;
printf("%d ",p->data);
free(p);
p = r;
}
}
10.将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变。
LinkList divideList(LinkList &LA)
{
int count = 1;
LinkList LB = (LinkList)malloc(sizeof(LNode));
LNode *rA = LA,*rB =LB, *p = LA->next;
while(p)
{
if(count%2 == 1)
{
rA->next = p;
rA = p;
}
else
{
rB->next = p;
rB = p;
}
count++;
p = p->next;
}
rA->next = NULL;
rB->next = NULL;
return LB;
}
11.设C={a1,b1,a2,b2,…,an,bn}为线性表,采用带头结点的hc单链表存放,设计一个就地算法,将其拆分为两个线性表,使得A={a1,a2,a3,…,an},B={bn,bn-1,…,b1}。
void divideList2(LinkList &LC)
{
LinkList LA = (LinkList)malloc(sizeof(LNode));
LinkList LB = (LinkList)malloc(sizeof(LNode));
int count = 1;
LNode *p = LC->next,*rA = LA,*r;
while(p)
{
if(count%2 == 1)
{
rA->next = p;
rA = p;
p = p->next;
}
else
{
r = p->next;
p->next = LB->next;
LB->next = p;
p = r;
}
count++;
}
rA->next = NULL;
printLinkList(LA);
printLinkList(LB);
}
12…在一个递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复元素,例如(7,10,10,21,30,42,42,51,70)将变成(7,10,21,30,42,51,70)
void delSameElem(LinkList &L)
{
LNode *pre = L->next,*p = pre->next;
while(p)
{
if(pre->data == p->data)
{
pre->next = p->next;
free(p);
p = pre->next;
}
else
{
pre = p;
p = p->next;
}
}
printLinkList(L);
}
13.假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。
14.设A和B是两个单链表(带头结点),其中元素递增有序。设计一个算法从A和B中的公共元素产生链表C,要求不破坏A、B结点。
LinkList findCommon(LinkList L1,LinkList L2)
{
LinkList L3 = (LinkList)malloc(sizeof(LNode));
LNode *p = L1->next,*q = L2->next,*r = L3,*s;
while(p&&q)
{
if(p->data < q->data)
p = p->next;
else if(q->data < p->data)
q = p->next;
else
{
s = (LNode *)malloc(sizeof(LNode));
s->data = p->data;
r->next = s;
r = s;
p = p->next;
q = q->next;
}
}
r->next = NULL;
return L3;
}
15.已知两个链表A和B分别表示两个集合,其元素递增排列。编制函数,求A与B的交集,并存放于A链表中。
void find_CommonElem(LinkList &LA, LinkList &LB)
{
LNode *p = LA->next, *q = LB->next,*r = LA,*s;
while(p&&q)
{
if(p->data < q->data)
{
s = p->next;
free(s);
p = s;
}
else if(p->data > q->data)
{
s = q->next;
free(s);
q = s;
}
else
{
r->next = p;
r = p;
p = p->next;
s = q->next;
free(s);
q = s;
}
}
r->next = NULL;
while(p)
{
s = p->next;
free(s);
p = s;
}
while(q)
{
s = q->next;
free(s);
q = s;
}
}
16.两个整数序列A = a1,a2,a3,…,am和B = b1,b2,b3,…,bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列
int isNotChildStr(LinkList LA,LinkList LB)
{
LNode *p = LA->next,*q = LB->next,*r = p;
if(getLength(LA) < getLength(LB))
return 0;
while(p&&q)
{
if(q->data == p->data)
{
q = q->next;
p = p->next;
}
else
{
r = r->next;
p = r;
q = LB->next;
}
}
if(q == NULL)
return 1;
else
return 0;
}
17.设计一个算法用来判断带头结点的循环双链表是否对称。
int isNotSymmetry(DLinkList L)
{
DNode *p = L->next, *q = L->prior;
while(p != q)
{
if(p->data == q->data)
{
p = p->next;
q = q->prior;
}
else
return 0;
}
return 1;
}
18.有两个循环单链表,链表头指针分别为h1和h2,编写一个函数将链表h2连接到链表h1之后,要求链接后的链表仍保持循环链表形式。
void mergeList(LinkList &h1, LinkList &h2)
{
LNode *p = h1, *q =h2;
while(h1->next != h1)
p = p->next;
while(h2->next != h2)
q= q->next;
p->next = h2;
q->next = h1;
}
19.设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出。然后将该节点从中删除,直到单链表为空,再删除表头结点。
void Del_Min2(LinkList &L)
{
LNode *p = L->next, *pre = L, *min = L->next,*minpre = L;
while(p->next != L)
{
while(p != L)
{
if(p->data < min->data)
{
min = p;
minpre = pre;
}
pre = p;
p = p->next;
}
printf("%d ",min->data);
minpre->next = min->next;
free(min);
p = L->next;
pre = L;
min = L->next;
minpre = L;
}
free(L);
}