设计算法Reverse( ),将带头结点的单链表A逆置,要求利用原有链表的链点,最后输出原单链表和逆置后的单链表。
参考答案(两种):
1.
void Reverse( LinkList *a )//注意此处是*而且linklist本身是个指针类型
//(即a是指向指针的指针),所以下面全部用(*a)->next,别问我怎么知道....
{
PNode p = (*a)->next;
PNode q = NULL;//初始化
PNode r = NULL;//顺序:q->r->a1
while (p)//p == null 结束
{
r = q;
q = p;//逆置后的后移机制变化,这两句都是将r,q在A链表中的位置后移
p = p->next;//p去冲锋陷阵,弄下一个元素
q->next = r;//逆置的关键步骤,让q指向前一个元素
}
(*a)->next = q;
}
2.
void Reverse(LinkList* a)
{
PNode p = (*a)->next; // p指向第一个结点
(*a)->next = NULL; // 断开原链表与新链表的连接
while (p)
{
PNode temp = p->next; // 保存下一个结点的位置
p->next = (*a)->next; // 将p结点插入到新链表的头部
(*a)->next = p;
p = temp; // p指向下一个结点
}
}
带头结点的单链表结点定义如下:
typedef int DataType;
typedef struct Node
{
DataType data; // data域用于存储数据元素
struct Node *next; // next域用于存放指向其后继的指针
}LNode, *PNode, *LinkList; // LinkList为头指针
函数接口定义:
void Reverse( LinkList *a );
*a
是原单链表的头指针。
裁判测试程序样例:
#include<stdio.h>
#include<stdlib.h>
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node* next;
}LNode, * PNode, * LinkList;
int InitLinkList(LinkList* head)
{ // 初始化单链表,开辟头结点
*head = (LinkList)malloc(sizeof(LNode));
if (!head)
{
printf("初始化链表错误!\n");
return 0;
}
(*head)->next = NULL;
return 1;
}
PNode LinkListInsert(LinkList h, int pos, DataType x)
{ // 在单链表h的第pos个位置插入x值的元素
PNode p = h, q;
int i = 0;
while (p && i < pos - 1)
{
p = p->next;
i++;
}
if (!p || i > pos - 1)
{
printf("插入位置不合法!\n");
return NULL;
}
q = (PNode)malloc(sizeof(LNode));
if (!q)
{
printf("不能生成新结点\n");
return NULL;
}
q->data = x;
q->next = p->next;
p->next = q;
return q;
}
void DestroyLinkList(LinkList h)
{ // 销毁单链表
PNode p = h->next;
while (h)
{
p = h;
h = h->next;
free(p);
}
}
void TraverseLinkList(LinkList h)
{ // 遍历单链表
PNode p = h->next;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int BnotinA(LinkList a, LinkList b)
{ // 判链表B的链点是否来自链表A
PNode pb = b->next;
PNode pa = a->next;
if (!pa)
{
return 1;
}
if (!pb)
{
return 1;
}
while (pa)
{
if ((DataType)pb != pa->data)
{
pa = pa->next;
continue;
}
return 0;
}
return 1;
}
/* 本题要求函数 */
void Reverse(LinkList* a);
int main()
{
LinkList h, aa1, pa = NULL;
DataType x;
char ch;
int pos = 1;
InitLinkList(&h);
InitLinkList(&aa1);
do
{
scanf("%d", &x); // 某些编译器要求此处改为scanf_s
pa = LinkListInsert(h, pos, x);
if (pa != NULL)
{
LinkListInsert(aa1, pos, (DataType)pa);
}
pos++;
} while ((ch = getchar()) != '\n');
printf("单链表A是\n");
TraverseLinkList(h);
Reverse(&h);
if (BnotinA(aa1, h) != 1)
{
printf("就地逆置后的单链表为\n");
TraverseLinkList(h);
}
DestroyLinkList(h);
return 0;
}
/* 请在这里填写答案 */
输入样例:
11 22 33 44 55 66 77 88 99
输出样例:
单链表A是
11 22 33 44 55 66 77 88 99
就地逆置后的单链表为
99 88 77 66 55 44 33 22 11