2009
设置指针*q和*p,*q和*p间隔k-1,故当*p指向尾结点时,*q正好指向倒数第k个结点。我的*p是指向第一个元素结点,*q指向头结点(也可以指向第一个元素结点),*p每向后移一位,i++,当i>=k-2时,移动*q(若*q指向第一个元素结点,那判别条件也相应变化)。
#include <iostream>
using namespace std;
typedef struct LNode
{ //定义单链表结点类型
int data; //数据域:每个结点存放一个数据元素
struct LNode *next; //指针域:指针指向下一个结点
}LNode, *LinkList;
LinkList List_TailInsert(LinkList &L)
{
int x;
L = (LinkList)malloc(sizeof(LNode)); //建立头结点
L->next = NULL;
LNode *s,*r = L; //建立表尾指针
printf("请输入插入的值:\n");
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; //返回头结点L
}
int Search_k(LinkList L)
{
int i = 0;
LNode *p = L->next, *q = L;
while(p->next != NULL)
{
if(i >= k - 2)
{
p = p->next;
q = q->next;
}
else
{
p = p->next;
i++;
}
}
printf("%d", q->data);
}
int main()
{
int flag;
LinkList L; //声明一个指向单链表的指针
List_TailInsert(L);
Search_k(L);
return 0;
}
2012
和2.3.7习题里的第八题类似,都是先让较长的单链表的指针先后移。
#include <iostream>
using namespace std;
typedef struct LNode
{ //定义单链表结点类型
int data; //数据域:每个结点存放一个数据元素
struct LNode *next; //指针域:指针指向下一个结点
}LNode, *LinkList;
LNode *Common(LinkList str1, LinkList str2)
{
int len1, len2, dist;
LNode *p1 = str1->next;
LNode *p2 = str2->next;
len1 = Length(str1), len2 = Length(str2);
if(len1 > len2)
{
dist = len1 - len2;
for(int i = 0; i < dist; i++)
p1 = p1->next;
}
if(len1 < len2)
{
dist = len2 - len1;
for(int i = 0; i < dist; i++)
p2 = p2->next;
}
while(p1 && p2)
{
if(p1->data == p2->data)
return p1;
p1 = p1->next;
p2 = p2->next;
}
}
int Length(LinkList L)
{
int num = 0;
LNode *p = L->next;
while(p)
{
num++;
p = p->next;
}
return num;
}
2014
若该结点不是叶子结点,则用先序遍历的方法前往下一层,deep+1,一直递归到最后一层,找到叶子结点,deep乘以该点的权值,再寻找其他叶子结点,把wpl相加得到最终值。
typedef struct BiTNode
{
int weight;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
int WPL(BiTree root)
{
return wpl_PreOrder(root, 0);
}
int wpl_PreOrder(BiTree root, int deep)
{
static int wpl = 0;
if(root->lchild == NULL && root->rchild == NULL)
wpl += deep * root->weight;
if(root->lchild != NULL)
wpl_PreOrder(root->lchild, deep + 1);
if(root->rchild != NULL)
wpl_PreOrder(root->rchild, deep + 1);
return wpl;
}
2015
题中暗示了可以用数组来记录该元素是否出现过。
#include <iostream>
using namespace std;
typedef struct LNode
{ //定义单链表结点类型
int data; //数据域:每个结点存放一个数据元素
struct LNode *link; //指针域:指针指向下一个结点
}LNode, *LinkList;
LinkList Delete_Same(LinkList &head)
{
int A[n + 1] = {0}; // |data|<=n,故可能出现的最大值为n,因此数组长度为n+1
LNode *p = head->link;
LNode *pre = head, *q;
while(p)
{
if(A[abs(p->data)] == 0) //若该位置为0,说明该元素尚未出现
{
A[abs(p->data)] = 1;
pre = p;
p = p->link;
}
else //该位置为1,说明该元素出现过,故将其删除
{
q = p;
p = p->link;
pre->link = q->link;
free(q);
}
}
}
2017
2019
将后半段链表原地逆置,此时分裂成了两个表,表1为原表的前半段,表2为原表逆置后的后半段,将表2的元素插入表1中。
#include <iostream>
using namespace std;
typedef struct LNode
{ //定义单链表结点类型
int data; //数据域:每个结点存放一个数据元素
struct LNode *next; //指针域:指针指向下一个结点
}LNode, *LinkList;
void change_list(LinkList &L)
{
LNode *p, *q, *r, *s;
p = q = L;
while(q->next)
{
p = p->next;
q = q->next;
if(q->next)
q = q->next;
}
q = p->next; //相当于p为后半段链表的头结点
p->next = NULL; //将其断开
while(q) //头插法逆置后半段
{
r = q->next; //趁q还未改变时,将其赋值给r
q->next = p->next;
p->next = q;
q = r;
}
s = L->next;
q = p->next;
p->next = NULL;
while(q) //相当于把后半段逆置后,插入前半段
{
r = q->next;
q->next = s->next;
s->next = q;
s = q->next;
q = r;
}
}
2019