(1)题目:单链表A 和 B (带表头结点),元素递增有序。设计算法将A 和 B归并成一个按照元素值依然递增有序的链表C,C由A和B的结点组成。
分析:A,B有序,可以从A,B中挑出最小的元素插入C的尾部。若是一个插入完毕,另一个则只要链接到C的尾部。
代码:
typedef struct LNode
{
int data;
struct LNode *next; //指向后继结点的指针
}LNode;
void mergeLinkedList( LNode *&A, LNode *&B, LNode *&C) //要改变的变量使用引用型
{
LNode *p = A->next; //p 跟踪A的最小值结点
LNode *q = B->next; //q 跟踪B的最小值结点
LNode *r; //r 指向C的终端结点
C = A; //使用A头结点作为C的头结点
C->next = NULL;
free(B); // B的头结点无用,释放掉
r = C; //头结点
while( NULL != p && NULL != q )
{
if ( p->data <= q->data )
{
r->next = p;
p = p->next; // A移动元素
r = r->next; // C尾结点向后移动
}
else
{
r->next = q;
q = q->next; // B移动元素
r = r->next; // C尾结点向后移动
}
}
r->next = NULL; //此句话可以去掉,下面两个if语句必须有一个要执行
if ( NULL != p ) //还有剩余结点的链表链接在尾部
{
r->next = p;
}
if ( NULL != q )
{
r->next = q;
}
}
总结:1)尾插法建立单链表;2)单链表归并操作
引申:归并称为 递减的链表C。 (将插入过程改为头插入法即可)
代码:
void mergeLinkedListDescend( LNode *&A, LNode *&B, LNode *&C)
{
LNode *p = A->next; //p 跟踪A的最小值结点
LNode *q = B->next; //q 跟踪B的最小值结点
LNode *s; //用 S来接受新的结点插入链表C的前端
C = A; //使用A头结点作为C的头结点
C->next = NULL;
free(B); // B的头结点无用,释放掉
while( NULL != p && NULL != q )
{
if ( p->data <= q->data ) //链表的头插入法
{
s = p; //将 p 赋值给 接受新结点的 s
p = p->next; // A移动元素
s->next = C->next; // s 所指向新结点的指针域next 指向C中的开始结点
C->next = s; // 头结点的指针域next指向 s结点,使得s称为新的开始结点
}
else
{
s = q; //将 q 赋值给 接受新结点的 s
q = q->next; // B移动元素
s->next = C->next; // s 所指向新结点的指针域next 指向C中的开始结点
C->next = s; // 头结点的指针域next指向 s结点,使得s称为新的开始结点
}
}
while ( NULL != p ) //还有剩余结点的链表逐个插入到C的头部
{
s = p;
p = p->next;
s->next = C->next; // 这两句插入顺序不能颠倒。 后继结点先写
C->next = s; // 这两句插入顺序不能颠倒。
}
while ( NULL != q )
{
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
(2)题目:查找链表C(带头结点)中是否存在一个值为 x 的结点,若存在,则删除该结点并返回1,否则返回0.
代码:
int SearchAndDelete(LNode *&C, int x)
{
LNode *p;
LNode *q;
p = C;
//查找部分 开始
while( NULL != p)
{
if ( x == p->next->data )
{
break;
}
p = p->next;
}
//查找部分结束
if ( NULL == p->next )
{
return 0;
}
else
{
//删除部分开始
q = p->next;
p->next = p->next->next; //将p的指针域next指向原来p的下一个结点的下一个结点,即可删除 或者写成 p->next = q->next;
free(q); //释放q所指结点的内存空间
//删除部分结束
return 1;
}
}
附录:假设有n个元素已经储存在数组a中,下面分别是尾插法与头插法建立链表C
//尾插法
void CreateListR(LNode *&C, int a[], int n)
{
LNode *s; //s用来指向新申请的结点
LNode *r; //r指向C的终端结点
int i;
C = (LNode*) malloc( sizeof(LNode)); // 申请C的头结点空间
C->next = NULL;
r = C;
for ( i = 1; i <= n; ++ i )
{
s = (LNode*) malloc( sizeof(LNode)); //s指向新申请的结点
s->data = a[i]; //新申请的结点接收a的一个元素
r->next = s; //r来接纳新结点
r = r->next; //r指向终端结点,以便接纳下一个到来的结点
}
r->next = NULL; //a中的元素全部装入链表C中,C的终端指针为NULL
}
//头插法
void CreateListF(LNode *&C, int a[], int n)
{
LNode *s;
int i;
C = (LNode*) malloc( sizeof(LNode)); // 申请C的头结点空间
C->next = NULL;
for ( i = 1; i <= n; ++ i )
{
s = (LNode*) malloc( sizeof(LNode)); //s指向新申请的结点
s->data = a[i]; //新申请的结点接收a的一个元素
/* 下面两句为 头插法 的关键步骤*/
s->next = C->next; //s所指新结点的指针域next指向C中的开始结点
C->next = s; //头结点的指针域next指向s结点,使得s成为了新的开始结点
}
}
<pre name="code" class="cpp">//整表删除
int ClearList(LNode *&C)
{
LNode *p;
LNode *q;
p = C->next;
while(p)
{
q = p->next;
free(p);
p = q;
}
C->next = NULL;
return 1;
}