第2章 线性表
2.3.1 设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点。
#include
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList init()
{
LinkList head = (LinkList)malloc(sizeof(LNode));
assert(head);
int n;
ElemType x;
scanf("%d", &n);
scanf("%d", &x);
head->data = x;
head->next = NULL;
LNode *tail = head;
for (int i = 1; i < n; i++) {
LinkList temp = (LinkList)malloc(sizeof(LNode));
assert(temp);
scanf("%d", &x);
temp->data = x;
tail->next = temp;
temp->next = NULL;
tail = tail->next;
}
return head;
}
void Del_X_3(LinkList & L, ElemType x)
{
LNode *p;
if (L == NULL) return;
if (L->data == x) {
p = L;
L = L->next;
free(p);
Del_X_3(L, x);
} else {
Del_X_3(L->next, x);
}
}
void print_list(LinkList L)
{
LNode *p = L;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
LinkList L = init();
ElemType x;
scanf("%d", &x);
Del_X_3(L, x);
print_list(L);
return 0;
}
2.3.2 在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
void Del_X_1(LinkList & L, ElemType x)
{
LNode *p = L->next, *pre = L, *q;
while (p != NULL) {
if (p->data == x) {
q = p;
p = p->next;
pre->next = p;
free(q);
} else {
pre = p;
p = p->next;
}
}
}
void Del_X_2(LinkList & L, ElemType x)
{
LNode *p = L->next, *r = L, *q;
while (p != NULL) {
if (p->data != x) {
r->next = p;
r = p;
p = p->next;
} else {
q = p;
p = p->next;
free(q);
}
}
r->next = NULL;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList L = NULL;
L = List_TailInsert(L);
ElemType x;
scanf("%d", &x);
Del_X_1(L, x);
print_list(L);
return 0;
}
2.3.3 设L为带头结点的单链表,编写算法实现从尾到头反响输出每个结点的值。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
void print(ElemType x)
{
printf("%d ", x);
}
void R_Print(LinkList L)
{
if (L->next != NULL) R_Print(L->next);
if (L != NULL) print(L->data);
}
void R_Ignore_Head(LinkList L)
{
if (L != NULL) R_Print(L->next);
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList L = NULL;
L = List_TailInsert(L);
R_Ignore_Head(L);
printf("\n");
return 0;
}
2.3.4 编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设最小值结点是唯一的)。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
LinkList Delete_Min(LinkList & L)
{
LNode *pre = L, *p = pre->next;
LNode *minpre = pre, *minp = p;
while (p != NULL) {
if (p->data < minp->data) {
minp = p;
minpre = pre;
}
pre = p;
p = p->next;
}
minpre->next = minp->next;
free(minp);
return L;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList L = NULL;
L = List_TailInsert(L);
L = Delete_Min(L);
print_list(L);
return 0;
}
2.3.5 编写算法将带头结点的单链表就地逆置。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
LinkList Reverse_1(LinkList L)
{
LNode *p, *r;
p = L->next;
L->next = NULL;
while (p != NULL) {
r = p->next;
p->next = L->next;
L->next = p;
p = r;
}
return L;
}
LinkList Reverse_2(LinkList L)
{
LNode *p, *r;
p = L->next;
L->next = NULL;
while (p != NULL) {
r = p;
p = p->next;
r->next = L->next;
L->next = r;
}
return L;
}
LinkList Reverse_3(LinkList L)
{
LNode *pre, *p = L->next, *r = p->next;
p->next = NULL;
while (r != NULL) {
pre = p;
p = r;
r = r->next;
p->next = pre;
}
L->next = p;
return L;
}
void print_list(LinkList * L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList L = NULL;
L = List_TailInsert(L);
Reverse_3(L);
print_list(L);
return 0;
}
2.3.6 有一个带头结点的单链表L,设计一个算法使其元素递增有序。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
void Sort(LinkList & L)
{
LNode *p = L->next, *pre;
LNode *r = p->next;
p->next = NULL;
p = r;
while (p != NULL) {
r = p->next;
pre = L;
while (pre->next != NULL && pre->next->data < p->data)
pre = pre->next;
p->next = pre->next;
pre->next = p;
p = r;
}
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList L = NULL;
L = List_TailInsert(L);
Sort(L);
print_list(L);
return 0;
}
2.3.7 设在一个带头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素(若存在)。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
void RangeDelete(LinkList & L, int min, int max)
{
LNode *pre = L, *p = L->next;
while (p != NULL) {
if (p->data > min && p-> data < max) {
pre->next = p->next;
free(p);
p = pre->next;
} else {
pre = p;
p = p->next;
}
}
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList L = NULL;
L = List_TailInsert(L);
int a, b;
scanf("%d%d", &a, &b);
RangeDelete(L, a, b);
print_list(L);
return 0;
}
2.3.8 给定两个单链表,编写算法找出两个链表的公共结点。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
int Length(LinkList L)
{
int res = 0;
LNode *p = L->next;
while (p != NULL) {
p = p->next;
res++;
}
return res;
}
LinkList Search_1st_Common(LinkList L1, LinkList L2)
{
int len1 = Length(L1), len2 = Length(L2), dist = 0;
LinkList longList = NULL, shortList = NULL;
if (len1 > len2) {
longList = L1->next;
shortList = L2->next;
dist = len1 - len2;
} else {
longList = L2->next;
shortList = L1->next;
dist = len2 - len1;
}
while (dist--)
longList = longList->next;
while (longList != NULL) {
if (longList->data == shortList->data) {
return longList;
} else {
longList = longList->next;
shortList = shortList->next;
}
}
return NULL;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList L1 = NULL;
L1 = List_TailInsert(L1);
LinkList L2 = NULL;
L2 = List_TailInsert(L2);
LinkList L3 = NULL;
L3 = Search_1st_Common(L1, L2);
while (L3 != NULL) {
printf("%d ", L3->data);
L3 = L3->next;
}
printf("\n");
return 0;
}
2.3.9 给定一个带头结点的单链表,设head为头指针,结点结构为(data,next),data为整形元素,next为指针,试写出算法:按递增次序输出单链表中各结点的数据元素,并释放结点所占的存储空间。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
void print(int n)
{
printf("%d ", n);
}
void Min_Delete(LinkList & head)
{
while (head->next != NULL) {
LNode *pre = head;
LNode *p = head->next;
while (p->next != NULL) {
if (p->next->data < pre->next->data)
pre = p;
p = p->next;
}
print(pre->next->data);
LNode *u = pre->next;
pre->next = u->next;
free(u);
}
free(head);
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList head = NULL;
head = List_TailInsert(head);
Min_Delete(head);
return 0;
}
2.3.10 将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
LinkList DisCreat_1(LinkList & A)
{
int i = 0;
LinkList B = (LinkList)malloc(sizeof(LNode));
B->next = NULL;
LNode *ra = A, *rb = B;
LNode *p = A->next;
A->next = NULL;
while (p != NULL) {
i++;
if (i % 2 == 0) {
rb->next = p;
rb = p;
} else {
ra->next = p;
ra = p;
}
p = p->next;
}
ra->next = NULL;
rb->next = NULL;
return B;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList A = NULL;
A = List_TailInsert(A);
LinkList B = NULL;
B = DisCreat_1(A);
print_list(A);
print_list(B);
return 0;
}
2.3.11 设 C = { a 1 , b 1 , a 2 , b 2 , . . . , a n , b n } C = \{a_{1},b_{1},a_{2},b_{2},...,a_{n},b_{n}\} C={a1,b1,a2,b2,...,an,bn}为线性表,采用带头结点的hc单链表存放,设计一个就地算法,将其拆分为两个线性表,使得 A = { a 1 , a 2 , . . . , a n } A=\{a_{1},a_{2},...,a_{n}\} A={a1,a2,...,an}, B = { b n , . . . , b 2 , b 1 } B=\{b_{n},...,b_{2},b_{1}\} B={bn,...,b2,b1}。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
LinkList DisCreat_2(LinkList & A)
{
LinkList B = (LinkList)malloc(sizeof(LNode));
B->next = NULL;
LNode *p = A->next, *q;
LNode *ra = A;
while (p != NULL) {
ra->next = p;
ra = p;
p = p->next;
if (p != NULL) q = p->next;
p->next = B->next;
B->next = p;
p = q;
}
ra->next = NULL;
return B;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList A = NULL;
A = List_TailInsert(A);
LinkList B = NULL;
B = DisCreat_2(A);
print_list(A);
print_list(B);
return 0;
}
2.3.12 在一个递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复的元素。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
void Del_Same(LinkList & L)
{
LNode *p = L->next, *q;
if (p == NULL) return;
while (p->next != NULL) {
q = p->next;
if (p->data == q->data) {
p->next = q->next;
free(q);
} else p = p->next;
}
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList L = NULL;
L = List_TailInsert(L);
Del_Same(L);
print_list(L);
return 0;
}
2.3.13 假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,要求利用原来两个单链表的结点存放归并后的单链表。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
void MergeList(LinkList & La, LinkList & Lb)
{
LNode *r, *pa = La->next, *pb = Lb->next;
La->next = NULL;
while (pa && pb) {
if (pa->data <= pb->data) {
r = pa->next;
pa->next = La->next;
La->next = pa;
pa = r;
} else {
r = pb->next;
pb->next = La->next;
La->next = pb;
pb = r;
}
}
if (pa) pb = pa;
while (pb) {
r = pb->next;
pb->next = La->next;
La->next = pb;
pb = r;
}
free(Lb);
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList La = NULL;
La = List_TailInsert(La);
LinkList Lb = NULL;
Lb = List_TailInsert(Lb);
MergeList(La, Lb);
print_list(La);
return 0;
}
2.3.14 设A和B是两个单链表(带头结点),其中元素递增有序。设计一个算法从A和B中的公共元素产生单链表C,要求不破坏A,B的结点。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
LinkList Get_Common(LinkList A, LinkList B)
{
LNode *p = A->next, *q = B->next, *r, *s;
LinkList C = (LinkList)malloc(sizeof(LNode));
r = C;
while (p != NULL && q != NULL) {
if (p->data < q->data) p = p->next;
else if (p->data > q->data) q = q->next;
else {
s = (LinkList)malloc(sizeof(LNode));
s->data = p->data;
r->next = s;
r = s;
p = p->next;
q = q->next;
}
}
r->next = NULL;
return C;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList A = NULL;
A = List_TailInsert(A);
LinkList B = NULL;
B = List_TailInsert(B);
LinkList C = NULL;
C = Get_Common(A, B);
print_list(C);
return 0;
}
2.3.15 已知两个链表A和B分别表示两个集合,其元素递增排列。编制函数,求A与B的交集,并存放于A链表中。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList List_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
LinkList Union(LinkList & la, LinkList & lb)
{
LNode *pa = la->next, *pb = lb->next, *pc = la, *u;
while (pa && pb) {
if (pa->data == pb->data) {
pc->next = pa;
pc = pa;
pa = pa->next;
u = pb;
pb = pb->next;
free(u);
} else if (pa->data < pb->data) {
u = pa;
pa = pa->next;
free(u);
} else {
u = pb;
pb = pb->next;
free(u);
}
}
while (pa) {
u = pa;
pa = pa->next;
free(u);
}
while (pb) {
u = pb;
pb = pb->next;
free(u);
}
pc->next = NULL;
free(lb);
return la;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != NULL) {
p = p->next;
printf("%d ", p->data);
}
printf("\n");
}
int main()
{
LinkList la = NULL;
la = List_TailInsert(la);
LinkList lb = NULL;
lb = List_TailInsert(lb);
LinkList A = NULL;
A = Union(la, lb);
print_list(A);
return 0;
}
2.3.16 两个整数序列A和B以及存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列。(假定A和B均无头结点)
#include
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList init()
{
LinkList head = (LinkList)malloc(sizeof(LNode));
assert(head);
int n;
ElemType x;
scanf("%d", &n);
scanf("%d", &x);
head->data = x;
head->next = NULL;
LNode *tail = head;
for (int i = 1; i < n; i++) {
LinkList temp = (LinkList)malloc(sizeof(LNode));
assert(temp);
scanf("%d", &x);
temp->data = x;
tail->next = temp;
temp->next = NULL;
tail = tail->next;
}
return head;
}
int Pattern(LinkList A, LinkList B)
{
LNode *p = A, *q = B, *pre = p;
while (p && q) {
if (p->data == q->data) {
p = p->next;
q = q->next;
} else {
pre = pre->next;
p = pre;
q = B;
}
}
if (q == NULL) return 1;
else return 0;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
LinkList A = init();
LinkList B = init();
if (Pattern(A, B)) printf("Yes\n");
else printf("No\n");
return 0;
}
2.3.17 设计一个算法用于判断带头结点的循环双链表是否对称。
#include
#include
#include
typedef int ElemType;
typedef struct DNode {
ElemType data;
struct DNode *prior, *next;
} DNode, *DLinkList;
void insert(DLinkList & DL)
{
DL = (DLinkList)malloc(sizeof(DNode));
DNode *s, *r = DL;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (DLinkList)malloc(sizeof(DNode));
scanf("%d", &x);
s->data = x;
r->next = s;
s->prior = r;
r = s;
}
DL->prior = s;
r->next = DL;
}
int Symmetry(DLinkList L)
{
DNode *p = L->next, *q = L->prior;
while (p != q && q->next != p) {
if (p->data == q->data) {
p = p->next;
q = q->prior;
} else return 0;
}
return 1;
}
void print_dlist(DLinkList DL)
{
DNode *p = DL->next;
while (p != DL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
DLinkList DL = NULL;
insert(DL);
if (Symmetry(DL)) printf("Yes\n");
else printf("No\n");
print_dlist(DL);
return 0;
}
2.3.18 有两个循环单链表,链表头指针分别为h1和h2,编写一个函数将链表h2链接到链表h1之后,要求链接后的链表仍保持循环链表形式。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList init()
{
LinkList head = (LinkList)malloc(sizeof(LNode));
int n;
ElemType x;
scanf("%d", &n);
scanf("%d", &x);
head->data = x;
head->next = NULL;
LNode *tail = head;
for (int i = 1; i < n; i++) {
LinkList temp = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
temp->data = x;
tail->next = temp;
tail = temp;
}
tail->next = head;
return head;
}
void Link(LinkList & h1, LinkList & h2)
{
LNode *p, *q;
p = h1;
while (p->next != h1)
p = p->next;
q = h2;
while (q->next != h2)
q = q->next;
p->next = h2;
q->next = h1;
}
void print_list(LinkList L)
{
LNode *p = L;
while (p->next != L) {
printf("%d ", p->data);
p = p->next;
}
printf("%d ", p->data);
printf("\n");
}
int main()
{
LinkList h1 = init();
LinkList h2 = init();
//Link(h1, h2);
print_list(h1);
return 0;
}
2.3.19 设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出,然后将该结点从中删除,直到单链表空为止,再删除表头结点。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList Link_TailInsert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = L;
return L;
}
void Del_All(LinkList & L)
{
LNode *p, *pre, *minp, *minpre;
while (L->next != L) {
p = L->next;
pre = L;
minp = p;
minpre = pre;
while (p != L) {
if (p->data < minp->data) {
minp = p;
minpre = pre;
}
pre = p;
p = p->next;
}
printf("%d ", minp->data);
minpre->next = minp->next;
free(minp);
}
free(L);
}
int main()
{
LinkList L = NULL;
L = Link_TailInsert(L);
Del_All(L);
return 0;
}
2.3.20 设头指针为L的带表头结点的非循环双向链表,其每个结点中有一个访问频度域freq。在链表被启用前,其值初始化为零。每当在链表中进行一次Locate(L,x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度递减的顺序排列,同时最近访问的结点排在频度相同的结点前面,以便使频繁访问的结点总是靠近表头。编写符合上述要求的Locate(L,x)运算的算法。
#include
#include
#include
typedef int ElemType;
typedef struct DNode {
int freq;
ElemType data;
struct DNode *pred, *next;
} DNode, *DLinkList;
void insert(DLinkList & L)
{
L = (DLinkList)malloc(sizeof(DNode));
DNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (DLinkList)malloc(sizeof(DNode));
s->freq = 0;
scanf("%d", &x);
s->data = x;
r->next = s;
s->pred = r;
r = s;
}
L->pred = NULL;
r->next = NULL;
}
DLinkList Locate(DLinkList & L, ElemType x)
{
DNode *p = L->next, *q;
while (p && p->data != x)
p = p->next;
if (!p) {
printf("不存在值为x的结点\n");
exit(0);
} else {
p->freq++;
if (p->next != NULL)
p->next->pred = p->pred;
p->pred->next = p->next;
q = p->pred;
while (q != L && q->freq <= p->freq)
q = q->pred;
p->next = q->next;
q->next->pred = p;
p->pred = q;
q->next = p;
}
return p;
}
int main()
{
DLinkList L = NULL;
insert(L);
DLinkList p = NULL;
ElemType x;
scanf("%d", &x);
p = Locate(L, x);
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return 0;
}
2.3.21 已知一个带有头结点的单链表,在不改变链表的前提下,查找链表中倒数第k个位置上的结点。若查找成功,输出该结点的data域的值,并返回1;否则,只返回0。
#include
#include
#include
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *link;
} LNode, *LinkList;
void insert(LinkList & list)
{
list = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = list;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
s->data = x;
r->link = s;
r = s;
}
r->link = NULL;
}
int Search_k(LinkList list, int k)
{
LNode *p = list->link, *q = list->link;
int i = 0;
while (p != NULL) {
if (i < k) i++;
else q = q->link;
p = p->link;
}
if (i < k) return 0;
else {
printf("%d\n", q->data);
return 1;
}
}
void print(LinkList list)
{
LNode *p = list->link;
while (p != NULL) {
printf("%d ", p->data);
p = p->link;
}
printf("\n");
}
int main()
{
LinkList list = NULL;
insert(list);
int k;
scanf("%d", &k);
print(list);
if (Search_k(list, k)) printf("Yes\n");
else printf("No\n");
return 0;
}
2.3.22 设计一个时间上近可能高效的算法,找出由str1和str2所指向两个链表共同后缀的起始位置。
#include
#include
#include
#include
using namespace std;
typedef char ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode, *LinkList;
LinkList insert(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
int n;
ElemType x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (LinkList)malloc(sizeof(LNode));
cin >> x;
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
int Length(LinkList L)
{
int res = 0;
while (L->next != NULL) {
res++;
L = L->next;
}
return res;
}
LinkList Search_1st_Common(LinkList str1, LinkList str2)
{
int len1 = Length(str1), len2 = Length(str2), dist;
LinkList longlist, shortlist;
if (len1 > len2) {
longlist = str1->next;
shortlist = str2->next;
dist = len1 - len2;
} else {
longlist = str2->next;
shortlist = str1->next;
dist = len2 - len1;
}
while (dist--) longlist = longlist->next;
while (longlist != NULL) {
if (longlist->data == shortlist->data)
return longlist;
else {
longlist = longlist->next;
shortlist = shortlist->next;
}
}
return NULL;
}
int main()
{
LinkList str1 = NULL;
str1 = insert(str1);
LinkList str2 = NULL;
str2 = insert(str2);
LinkList p = Search_1st_Common(str1, str2);
printf("%c\n", p->data);
return 0;
}
2.3.23 用单链表保存m个整数,结点的结构为 [ d a t a ] [ l i n k ] [data][link] [data][link],且 [ d a t a ] ≤ n [data]\leq n [data]≤n(n为正整数)。设计一个算法,对于链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。
#include
#include
#include
typedef struct node {
int data;
struct node *link;
} NODE, *PNODE;
void insert(PNODE & h)
{
h = (PNODE)malloc(sizeof(NODE));
NODE *s, *r = h;
int n, x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (PNODE)malloc(sizeof(NODE));
scanf("%d", &x);
s->data = x;
r->link = s;
r = s;
}
r->link = NULL;
}
void func(PNODE & h, int n)
{
PNODE r, p = h;
int *q, m;
q = (int *)malloc(sizeof(int) * (n + 1));
for (int i = 0; i < n + 1; i++)
*(q + i) = 0;
while (p->link != NULL) {
m = p->link->data > 0 ? p->link->data : -(p->link->data);
if (*(q + m) == 0) {
*(q + m) = 1;
p = p->link;
} else {
r = p->link;
p->link = r->link;
free(r);
}
}
free(q);
}
void print(PNODE h)
{
while (h->link != NULL) {
h = h->link;
printf("%d ", h->data);
}
printf("\n");
}
int main()
{
PNODE h = NULL;
insert(h);
int n;
scanf("%d", &n);
func(h, n);
print(h);
return 0;
}
2.3.24 设计一个算法完成以下功能:判断一个链表是否有环,如果有,找出环的入口点并返回,否则返回NULL。
#include
#include
#include
typedef struct node {
int data;
struct node *link;
} NODE, *PNODE;
void insert(PNODE & h)
{
h = (PNODE)malloc(sizeof(NODE));
int n, x;
scanf("%d", &n);
scanf("%d", &x);
h->data = x;
h->link = NULL;
NODE *s, *r = h, *p;
for (int i = 1; i < n; i++) {
s = (PNODE)malloc(sizeof(NODE));
scanf("%d", &x);
s->data = x;
r->link = s;
r = s;
if (i == 1) p = r;
}
r->link = p;
}
NODE * FindLoopStart(NODE * head)
{
NODE *fast = head, *slow = head;
while (slow != NULL && fast->link != NULL) {
slow = slow->link;
fast = fast->link->link;
if (slow == fast) break;
}
if (slow == NULL || fast->link == NULL)
return NULL;
NODE *p1 = head, *p2 = slow;
while (p1 != p2) {
p1 = p1->link;
p2 = p2->link;
}
return p1;
}
int main()
{
PNODE h = NULL;
insert(h);
NODE *p = FindLoopStart(h);
printf("%d\n", p->data);
return 0;
}
2.3.25 设线性表 L = ( a 1 , a 2 , a 3 , . . . , a n − 2 , a n − 1 , a n ) L=(a_{1},a_{2},a_{3},...,a_{n-2},a_{n-1},a_{n}) L=(a1,a2,a3,...,an−2,an−1,an)采用带头结点的单链表保存,设计一个空间复杂度为 O ( 1 ) O(1) O(1)且时间上尽可能高效的算法,重新排列 L L L中的各结点,得到线性表 L ′ = ( a 1 , a n , a 2 , a n − 1 , a 3 , a n − 2 , . . . ) L^{\prime}=(a_{1},a_{n},a_{2},a_{n-1},a_{3},a_{n-2},...) L′=(a1,an,a2,an−1,a3,an−2,...)。
#include
#include
#include
typedef struct node {
int data;
struct node *next;
} NODE;
NODE * insert(NODE * L)
{
L = (NODE *)malloc(sizeof(NODE));
NODE *s, *r = L;
int n, x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
s = (NODE *)malloc(sizeof(NODE));
scanf("%d", &x);
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
void change_list(NODE * h)
{
NODE *p, *q, *r, *s;
p = q = h;
while (q->next != NULL) {
p = p->next;
q = q->next;
if (q->next != NULL) q = q->next;
}
q = p->next;
p->next = NULL;
while (q != NULL) {
r = q->next;
q->next = p->next;
p->next = q;
q = r;
}
s = h->next;
q = p->next;
p->next = NULL;
while (q != NULL) {
r = q->next;
q->next = s->next;
s->next = q;
s = q->next;
q = r;
}
}
void print(NODE * L)
{
while (L->next != NULL) {
L = L->next;
printf("%d ", L->data);
}
printf("\n");
}
int main()
{
NODE * L = NULL;
L = insert(L);
change_list(L);
print(L);
return 0;
}