习题一
将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间,不另外占用其他的存储空间。表中不允许有重复的数据。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* CreateNodeByTail(struct Node* headNode);
void printNode(struct Node* headNode);
void mergeNode(struct Node* headNodeA, struct Node* headNodeB);
int main()
{
struct Node* listA = NULL;
struct Node* listB = NULL;
struct Node* list1 = CreateNodeByTail(listA);
printNode(list1);
struct Node* list2 = CreateNodeByTail(listB);
printNode(list2);
fflush(stdout); //刷新输出缓冲区
printf("\n");
mergeNode(list1, list2);
printNode(list1);
return 0;
}
//后插法创建一个递增的单链表
struct Node* CreateNodeByTail(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->next = NULL;
struct Node* s; //申请的新结点
int numLength = 0;
printf("请输入单链表的长度:");
scanf_s("%d", &numLength);
int i = 0;
int num = 0;
struct Node* pre = headNode;
struct Node* p = headNode->next;
for (i = 0; i < numLength; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
//遍历已存入的数值
pre = headNode;
p = headNode->next;
while (p && p->data < num)
{
pre = p;
p = p->next;
}
if (p && p->data == num)
{
printf("已存在该数值,请重新输入。\n");
i--;
continue;
//中止本次for循环。
//跳过本次for循环体中剩下尚未执行的语句,立即进行下一次的for循环
//continue、break都只对一层循环起作用,用在内层循环时,只对内层循环其作用,对外层循环无影响。
}
s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
//找到第一个比num大的数p->data,将新结点s插入到p前面
if (p && p->data > s->data)
{
s->next = p;
pre->next = s;
}
if (!p) //s->data是最大的
{
pre->next = s;
s->next = NULL;
}
}
return headNode;
}
//打印单链表
void printNode(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 0;
for (i = 1; pMove != NULL; i++)
{
printf("%d ", pMove->data);
pMove = pMove->next;
}
printf("\nlist_length: %d\n", i);
}
//合并单链表
void mergeNode(struct Node* headNodeA, struct Node* headNodeB)
{
struct Node* p1 = headNodeA->next;
struct Node* p2 = headNodeB->next;
//因为在下面的while循环中直接比较data值,因此p1、p2必须初始化为首元结点
//否则无法输出!!!
struct Node* p3 = headNodeA;
struct Node* r = p2; //工具指针
while (p1 && p2)
{
if (p1->data < p2->data)
{
p3->next = p1;
p3 = p1;
p1 = p1->next;
}
else if (p1->data > p2->data)
{
p3->next = p2;
p3 = p2;
p2 = p2->next;
}
else
{
p3->next = p1;
p3 = p1;
p1 = p1->next;
r = p2;
p2 = p2->next;
free(r);
}
}
if (p1)
{
p3->next = p1;
p3 = p1;
p1 = p1->next;
}
else
{
p3->next = p2;
p3 = p2;
p2 = p2->next;
}
//此处为了保证将两个链表都循环完,最好用while(p1)、while(p2)
//但是经用长度相差较大的两个链表验证,用if也是可以的。
free(headNodeB);
}
习题二
将两个非递减的有序链表合并为一个非递增的有序链表。要求结果链表仍使用原来两个链表的存储空间,不另外占用其他的存储空间。表中允许有重复的数据。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* CreateNodeByTail(struct Node* headNode);
void printNode(struct Node* headNode);
void mergeNode(struct Node* headNodeA, struct Node* headNodeB);
int main()
{
struct Node* listA = NULL;
struct Node* listB = NULL;
struct Node* list1 = CreateNodeByTail(listA);
printNode(list1);
struct Node* list2 = CreateNodeByTail(listB);
printNode(list2);
fflush(stdout); //刷新输出缓冲区
printf("\n");
mergeNode(list1, list2);
printNode(list1);
return 0;
}
//后插法创建一个非递减的有序单链表
struct Node* CreateNodeByTail(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->next = NULL;
struct Node* s; //申请的新结点
int numLength = 0;
printf("请输入单链表的长度:");
scanf_s("%d", &numLength);
int i = 0;
int num = 0;
struct Node* pre = headNode;
struct Node* p = headNode->next;
for (i = 0; i < numLength; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
//遍历已存入的数值
pre = headNode;
p = headNode->next;
while (p && p->data < num)
{
pre = p;
p = p->next;
}
s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
//找到第一个比num大的数p->data(相等也是),将新结点s插入到p前面
s->next = p;
pre->next = s;
if (!p) //s->data是最大的
{
pre->next = s;
s->next = NULL;
}
}
return headNode;
}
//打印单链表
void printNode(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 0;
for (i = 1; pMove != NULL; i++)
{
printf("%d ", pMove->data);
pMove = pMove->next;
}
printf("\nlist_length: %d\n", i);
}
//合并单链表
void mergeNode(struct Node* headNodeA, struct Node* headNodeB)
{
struct Node* p1 = headNodeA->next;
struct Node* p2 = headNodeB->next;
//因为在下面的while循环中直接比较data值,因此p1、p2必须初始化为首元结点
//否则无法输出!!!
struct Node* p3 = headNodeA;
struct Node* r = p2; //工具指针
while (p1 && p2)
{
if (p1->data <= p2->data)
{
p3->next = p1;
p3 = p1;
p1 = p1->next;
}
else
{
p3->next = p2;
p3 = p2;
p2 = p2->next;
}
}
if (p1)
{
p3->next = p1;
p3 = p1;
p1 = p1->next;
}
else
{
p3->next = p2;
p3 = p2;
p2 = p2->next;
}
//此处为了保证将两个链表都循环完,最好用while(p1)、while(p2)
//但是经用长度相差较大的两个链表验证,用if也是可以的。
free(headNodeB);
}
***习题三
已知两个链表A和B分别表示两个集合,其元素递增排列。请设计一个算法,用于求出A与B的交集,并存放在A链表中。
思路:
求交集就是求两条链具有的相同元素的结点,A和B链结点一一比较,相同的A保留,B删除结点,不相同结点,由于是递增链,小的元素已经没有再比较的必要了,删去,当其中一条链走到结尾时,比较就结束了,只需把没有走到尾的链剩余结点清除即可。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* CreateNodeByTail(struct Node* headNode);
void printNode(struct Node* headNode);
void intersectionNode(struct Node* headNodeA, struct Node* headNodeB);
int main()
{
struct Node* listA = NULL;
struct Node* listB = NULL;
struct Node* list1 = CreateNodeByTail(listA);
printNode(list1);
struct Node* list2 = CreateNodeByTail(listB);
printNode(list2);
printf("\n");
intersectionNode(list1, list2);
printNode(list1);
return 0;
}
//后插法创建一个递增的单链表
struct Node* CreateNodeByTail(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->next = NULL;
struct Node* s; //申请的新结点
int numLength = 0;
printf("请输入单链表的长度:");
scanf_s("%d", &numLength);
int i = 0;
int num = 0;
struct Node* pre = headNode;
struct Node* p = headNode->next;
for (i = 0; i < numLength; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
//遍历已存入的数值
pre = headNode;
p = headNode->next;
while (p && p->data < num)
{
pre = p;
p = p->next;
}
if (p && p->data == num)
{
printf("已存在该数值,请重新输入。\n");
i--;
continue;
}
s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
//找到第一个比num大的数p->data,将新结点s插入到p前面
if (p && p->data > s->data)
{
s->next = p;
pre->next = s;
}
if (!p) //s->data是最大的
{
pre->next = s;
s->next = NULL;
}
}
return headNode;
}
//打印单链表
void printNode(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 0;
for (i = 1; pMove != NULL; i++)
{
printf("%d ", pMove->data);
pMove = pMove->next;
}
printf("\nlist_length: %d\n", i);
}
//求两个链表的交集
void intersectionNode(struct Node* L1, struct Node* L2)
{
//都是带头结点的链表,L1为A链,L2为B链
struct Node* q;
struct Node* p1 = L1->next;
struct Node* p2 = L2->next;
struct Node* L3 = L1;//使用第一条链的头结点
struct Node* p3 = L3;
while (p1 && p2)//只要一条链到尾就跳出
{
if (p1->data == p2->data)//相等保留
{
p3->next = p1;
p3 = p1;
p1 = p1->next;
q = p2;//第二条链删除一个节点
p2 = p2->next;
delete q;
}
/* headNodeA中与headNodeB只要相等的,就一定是交集中的元素,不管大小。
不管哪条链,小的元素对应节点删掉。
因为两个链表都是递增的,因此此处小的元素一定比对面链表中后面的任意一个结点都小,所以删掉。
较大的元素,对面链表中可能还会有与其相等的,所以不删。*/
else if (p1->data < p2->data)
{
q = p1;
p1 = p1->next;
delete q;
}
else
{
q = p2;
p2 = p2->next;
delete q;
}
}
//把剩余的节点清空
while (p1)
{
q = p1;
p1 = p1->next;
delete q;
}
while (p2)
{
q = p2;
p2 = p2->next;
delete q;
}
free(L2);
p3->next = NULL;//把新链尾巴置NULL,一定要有,不然在其他操作中报错
}
只会进行下图中非灰色部分的比较,红色为交集。
***习题四
已知两个链表A和B分别表示两个集合,其元素递增排列。请设计算法求出两个集合A和B的差集(即仅由在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* CreateNodeByTail(struct Node* headNode);
void printNode(struct Node* headNode);
int differenceList(struct Node* headNodeA, struct Node* headNodeB);
int main()
{
struct Node* listA = NULL;
struct Node* listB = NULL;
int num = 0;
struct Node* list1 = CreateNodeByTail(listA);
printNode(list1);
struct Node* list2 = CreateNodeByTail(listB);
printNode(list2);
printf("\n");
num = differenceList(list1, list2);
printNode(list1);
printf("\n差集链表中元素的个数为:%d\n",num);
return 0;
}
//后插法创建一个递增的单链表
struct Node* CreateNodeByTail(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->next = NULL;
struct Node* s; //申请的新结点
int numLength = 0;
printf("请输入单链表的长度:");
scanf_s("%d", &numLength);
int i = 0;
int num = 0;
struct Node* pre = headNode;
struct Node* p = headNode->next;
for (i = 0; i < numLength; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
//遍历已存入的数值
pre = headNode;
p = headNode->next;
while (p && p->data < num)
{
pre = p;
p = p->next;
}
if (p && p->data == num)
{
printf("已存在该数值,请重新输入。\n");
i--;
continue;
}
s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
//找到第一个比num大的数p->data,将新结点s插入到p前面
if (p && p->data > s->data)
{
s->next = p;
pre->next = s;
}
if (!p) //s->data是最大的
{
pre->next = s;
s->next = NULL;
}
}
return headNode;
}
//打印单链表
void printNode(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 0;
for (i = 1; pMove != NULL; i++)
{
printf("%d ", pMove->data);
pMove = pMove->next;
}
printf("\nlist_length: %d\n", i);
}
//差集
int differenceList(struct Node* headNodeA, struct Node* headNodeB)
{
struct Node* pa = headNodeA->next;
struct Node* pb = headNodeB->next;
struct Node* headNodeC = headNodeA;
struct Node* pc = headNodeC;
int count = 0;
/* headNodeA中与headNodeB不相等的,不管大小,都一定是差集元素。
只不过由于是递增序列,pa->data小的,可以不用再与headNodeB后面的元素比较;
而pa->data大的,要确认一下headNodeB后面没有与此pa—>data相等的了。 */
/* 在headNodeA 和 headNodeB中,比出比较小的那个,且对应单链表的指针往后移。
若pa->data比较小,则此pa->data一定是差集中的元素,将其添加至headNodeC中。headNodeA中的此pa->data元素比较完毕,pa往后移。因为此处的pb->data比较大,还可能与pa->data后面的元素相等,因此pb不动;
若pb->data比较小,此时还不能判断出此处的pa->data是不是差集中的元素。但因为是递增序列,该pb->data没有必要再与pa->data后面的值相比较。pb往后移,pa不动。*/
while (pa && pb)
{
if (pa->data < pb->data)
//因为两个都是递增的单链表,因此此时pa->data一定是差集元素
{
pc->next = pa;
pc = pa;
pa = pa->next;
pc->next = NULL;
count++;
}
else if (pa->data > pb->data)
{
pb = pb->next;
//万一pb后面有与pa->data相同的元素,则pa->data一定不是差集元素,进入第三个if判断
//如果pb后面的元素也都比此处的pa->data小,则此处的pa->data一定是差集元素,执行跳出该while循环后面的语句
//如果pb后面的元素出现比此处的pa->data大的,则此处的pa->data也一定是差集元素,执行第一个if判断
}
else //与pa->data相同的元素,则pa->data一定不是差集元素
{
pa = pa->next;
pb = pb->next;
}
}
//如果因为pa为NULL,跳出上面的while循环,则不用对pb进行任何处理
/* 如果因为pb为NULL,跳出上面的while循环,且此时pa不等于NULL,由于前面的元素都经过了比较,
则此时pa指向的元素一定是差集元素。如果后面还有,则全部都是差集元素。*/
if (pa)
{
pc->next = pa;
}
while (pa)
{
count++;
pa = pa->next;
//对于单链表,只要头结点定了,各元素之间用指针next相连接,因此此处不用再使用指针pc
}
free(headNodeB);
return count;
}
习题五
设计算法将一个带头结点的单链表A分解为两个具有相同结构的链表B和C,其中B表的结点为A表中值小于零的结点,而C表的结点为A表中值大于零的结点(链表A中的元素为非零整数,要求B、C表利用A表的结点)。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* CreateNode(struct Node* headNode);
void insertNodeByTail(struct Node* headNode);
void printNode(struct Node* headNode);
void Dividliist(struct Node* L1, struct Node* L2, struct Node* L3);
int main()
{
struct Node* listA = NULL;
struct Node* listB = NULL;
struct Node* listC = NULL;
struct Node* list1 = CreateNode(listA);
struct Node* list2 = CreateNode(listB);
struct Node* list3 = CreateNode(listC);
insertNodeByTail(list1);
printNode(list1);
printf("\n");
Dividliist(list1, list2, list3);
printNode(list2);
printNode(list3);
return 0;
}
//创建单链表并进行初始化
struct Node* CreateNode(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->next = NULL;
return headNode;
}
//后插法往单链表中增加结点
void insertNodeByTail(struct Node* headNode)
{
struct Node* r = headNode; //指向尾结点
struct Node* s; //申请的新结点
int numLength = 0;
printf("请输入单链表的长度:");
scanf_s("%d", &numLength);
int num = 0;
for (int i = 0; i < numLength; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
if (num == 0)
{
printf("请输入非0数值。\n");
i--;
continue;
}
s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
s->next = NULL;
r->next = s;
r = s;
}
}
//打印单链表
void printNode(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 0;
for (i = 1; pMove != NULL; i++)
{
printf("%d ", pMove->data);
pMove = pMove->next;
}
printf("\nlist_length: %d\n", i);
}
void Dividliist(struct Node* L1, struct Node* L2, struct Node* L3)
{
/*
function:将链表L1按元素的正负分为L2和L3两个链表
参数说明:L1为待分解的链表,L2为负数构成的链表的头结点,L3为正数构成的链表的头结点
*/
struct Node* p1 = L1->next;
struct Node* p2 = L2;
struct Node* p3 = L3;
while (p1)
{
if (p1->data < 0)
{
p2->next = p1;
p2 = p2->next;
}
else if (p1->data > 0)
{
p3->next = p1;
p3 = p3->next;
}
p1 = p1->next;
}
//L2和L3链表最后一个结点指向NULL
p2->next = NULL;
p3->next = NULL;
}
习题六
设计一个算法,通过一趟遍历确定长度为n的单链表中值最大的结点。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* CreateNode(struct Node* headNode);
void insertNodeByTail(struct Node* headNode);
void printNode(struct Node* headNode);
struct Node* maxNode(struct Node* headNode);
int main()
{
struct Node* listA = NULL;
struct Node* list1 = CreateNode(listA);
struct Node* max = list1;
insertNodeByTail(list1);
printNode(list1);
printf("\n");
max = maxNode(list1);
printf("最大值为:%d", max->data);
return 0;
}
//创建单链表并进行初始化
struct Node* CreateNode(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->next = NULL;
return headNode;
}
//后插法往单链表中增加结点
void insertNodeByTail(struct Node* headNode)
{
struct Node* r = headNode; //指向尾结点
struct Node* s; //申请的新结点
int numLength = 0;
printf("请输入单链表的长度:");
scanf_s("%d", &numLength);
int num = 0;
for (int i = 0; i < numLength; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
s->next = NULL;
r->next = s;
r = s;
}
}
//打印单链表
void printNode(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 0;
for (i = 1; pMove != NULL; i++)
{
printf("%d ", pMove->data);
pMove = pMove->next;
}
printf("\nlist_length: %d\n", i);
}
//寻找最大值
struct Node* maxNode(struct Node* headNode)
{
struct Node* p = headNode->next;
struct Node* max = p->next;
while (p != NULL)
{
if (p->data > max->data)
{
max = p;
}
p = p->next;
}
return max;
}
习题七
设计一个算法,将链表中所有结点的链接方向“原地”逆转,即要求仅利用原表的存储空间,换句话说,要求算法的空间复杂度为O(1)。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* CreateNode(struct Node* headNode);
void insertNodeByTail(struct Node* headNode);
void printNode(struct Node* headNode);
void Inverse(struct Node* headNode);
int main()
{
struct Node* listA = NULL;
struct Node* list1 = CreateNode(listA);
struct Node* max = list1;
insertNodeByTail(list1);
printNode(list1);
printf("\n");
Inverse(list1);
printNode(list1);
return 0;
}
//创建单链表并进行初始化
struct Node* CreateNode(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->next = NULL;
return headNode;
}
//后插法往单链表中增加结点
void insertNodeByTail(struct Node* headNode)
{
struct Node* r = headNode; //指向尾结点
struct Node* s; //申请的新结点
int numLength = 0;
printf("请输入单链表的长度:");
scanf_s("%d", &numLength);
int num = 0;
for (int i = 0; i < numLength; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
s->next = NULL;
r->next = s;
r = s;
}
}
//打印单链表
void printNode(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 0;
for (i = 1; pMove != NULL; i++)
{
printf("%d ", pMove->data);
pMove = pMove->next;
}
printf("\nlist_length: %d\n", i);
}
// 链表逆转算法(头插法的思想)
void Inverse(struct Node* headNode)
{
struct Node* p = headNode->next;
struct Node* q; //工具结点,防止断链
headNode->next = NULL;//将头结点的指针域记为空,从首元结点就开始头插法
while (p != NULL)
{
q = p->next; //工具结点,指向要进行头插法的p结点的下一个结点,防止断链
//对p结点进行头插法(总是将p指向的结点放到头结点headNode的后面)
p->next = headNode->next; //改变p指向结点的指针域
headNode->next = p; //改变头结点headNode的指针域
p = q; //此时p要后移,不能再通过p->next,要使用工具指针q保存的结点
}
}
习题八
设计一个算法,删除递增有序链表中值大于mink且小于maxk的所有元素(mink和maxk是给定的两个参数,其值可以和表中的元素相同,也可以不同)。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* CreateNodeByTail(struct Node* headNode);
void printNode(struct Node* headNode);
void Dlelte_Between(struct Node* headNode);
int main()
{
struct Node* listA = NULL;
struct Node* list1 = CreateNodeByTail(listA);
printNode(list1);
printf("\n");
Dlelte_Between(list1);
printNode(list1);
return 0;
}
//后插法创建一个递增的单链表
struct Node* CreateNodeByTail(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->next = NULL;
struct Node* s; //申请的新结点
int numLength = 0;
printf("请输入单链表的长度:");
scanf_s("%d", &numLength);
int i = 0;
int num = 0;
struct Node* pre = headNode;
struct Node* p = headNode->next;
for (i = 0; i < numLength; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
//遍历已存入的数值
pre = headNode;
p = headNode->next;
while (p && p->data < num)
{
pre = p;
p = p->next;
}
if (p && p->data == num)
{
printf("已存在该数值,请重新输入。\n");
i--;
continue;
//中止本次for循环。
//跳过本次for循环体中剩下尚未执行的语句,立即进行下一次的for循环
//continue、break都只对一层循环起作用,用在内层循环时,只对内层循环其作用,对外层循环无影响。
}
s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
//找到第一个比num大的数p->data,将新结点s插入到p前面
if (p && p->data > s->data)
{
s->next = p;
pre->next = s;
}
if (!p) //s->data是最大的
{
pre->next = s;
s->next = NULL;
}
}
return headNode;
}
//打印单链表
void printNode(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 0;
for (i = 1; pMove != NULL; i++)
{
printf("%d ", pMove->data);
pMove = pMove->next;
}
printf("\nlist_length: %d\n", i);
}
//删除递增有序链表中值大于mink且小于maxk的所有元素(等于mink或maxk的均保留)
void Dlelte_Between(struct Node* headNode)
{
int mink = 0;
int maxk = 0;
printf("请输入下限:");
scanf_s("%d", &mink);
printf("请输入上限:");
scanf_s("%d", &maxk);
struct Node* pre = headNode;
struct Node* p = headNode->next;
struct Node* q;
struct Node* s;
while (p && p->data <= mink)
{
pre = p;
p = p->next; // 查找第一个值>mink的结点
}
if (p)
{
while (p && p->data < maxk)
p = p->next; // 查找第一个值 ≥maxk的结点
q = pre->next; // 修改指针
pre->next = p; // 连接链表未被删除的部分
while (q != p)
{
s = q->next;
delete q;
q = s; // 释放结点空间
}
}
}
习题九
已知p指向双向循环链表中的一个结点,其结点结构为data、prior、next三个域,写出算法change(§,交换p所指向的结点及其前驱结点的顺序。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* piror;
struct Node* next;
};
struct Node* Initialization(struct Node* headNode);
void insertNode(struct Node* headNode);
void printlist(struct Node* headNode);
struct Node* inverselist(struct Node* HNode);
struct Node* change(struct Node* hNode);
int main()
{
struct Node* list1 = NULL;
struct Node* list2 = NULL;
struct Node* head11 = NULL;
struct Node* head22 = NULL;
struct Node* head1 = Initialization(list1);
insertNode(head1);
printlist(head1);
printf("\n改变所有结点的顺序:");
head11 = inverselist(head1);
printlist(head11);
struct Node* head2 = Initialization(list2);
insertNode(head2);
printlist(head2);
printf("\n改变指定结点与其前驱结点的顺序\n");
head22 = change(head2);
printlist(head22);
}
//创建双向循环链表并进行初始化
struct Node* Initialization(struct Node* headNode)
{
headNode = (struct Node*)malloc(sizeof(struct Node));
headNode->piror = headNode;
headNode->next = headNode;
return headNode;
}
//后插法插入结点
void insertNode(struct Node* headNode)
{
int num = 0;
int len = 0;
struct Node* r = headNode;
printf("请输入双向链表的长度:");
scanf_s("%d", &len);
for (int i = 0; i < len; i++)
{
printf("请输入第%d个数值:", i + 1);
scanf_s("%d", &num);
struct Node* s = (struct Node*)malloc(sizeof(struct Node));
s->data = num;
s->piror = r;
s->next = headNode;
r->next = s;
headNode->piror = s;
r = s;
}
}
//打印
void printlist(struct Node* headNode)
{
struct Node* pMove = headNode->next;
int i = 1;
while (pMove != headNode) //注意双向循环链表中的结束条件
{
printf("%d ", pMove->data);
i++;
pMove = pMove->next;
}
printf("\nlist_lenth : %d\n", i);
}
//更改链表中所有结点的顺序指向(交换p所指向的结点及其前驱结点的顺序)
struct Node* inverselist(struct Node* HNode)
{
struct Node* p = HNode->next->next;
struct Node* q; //工具指针,防止断链
//类似前插法
while (p != HNode) //注意双向循环链表中的结束条件
{
q = p->next;
p->piror->next = p->next;
p->next->piror = p->piror;
p->next = HNode->next;
HNode->next->piror = p;
p->piror = HNode;
HNode->next = p; //这个一定要放在最后
p = q;
}
return HNode;
}
//交换指针p所指向的结点及其前驱结点的顺序
struct Node* change(struct Node* hNode)
{
struct Node* p = hNode->next;
struct Node* pre; //工具指针
int num = 0;
printf("请输入要交换的结点数值:");
scanf_s("%d", &num);
//双向循环链表的按值查找
while (p != hNode && p->data != num)
{
p = p->next;
}
if (p == hNode && p->data != num)
{
printf("不存在该数值,请重新输入。\n");
hNode = change(hNode);
}
if (p != hNode && p->data == num)
{
pre = p->piror;
pre->next = p->next;
p->next->piror = pre;
p->piror = pre->piror;
p->next = pre;
pre->piror->next = p;
pre->piror = p;
}
return hNode;
}
习题十
已知长度为n的线性表A采用顺序存储结构,请写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法可删除线性表中所有值为item的数据元素。
#include <stdio.h>
//顺序表的存储结构
#define MAXSIZE 100 //顺序表可能达到的最大长度
typedef int ElemType; //自定义数据元素类型
typedef struct
{
ElemType* elem; //存储空间的基地址
int length; //当前长度,数据元素的个数
}SqList; //顺序表的结构类型为SqList
//初始化,构造一个空的顺序表L,并输入数据
void InitList(SqList& L)
{
int len;
L.elem = new ElemType[MAXSIZE]; //为顺序表分配一个大小为MAXSIZE的数组空间
if (!L.elem)
{
printf("Error");
return;
}
printf("Please input the length of the linear table:");
scanf_s("%d", &len);
L.length = len;
printf("Please input the elements of the linear table:\n");
for (int i = 0; i < len; i++)
{
scanf_s("%d", &L.elem[i]); //一个换行符代表一个数值输入结束
}
}
//删除值为item的元素
//将非item的数值依次写入
void ListDelete(SqList& L, int item)
{
int j = 0;
for (int i = 0; i < L.length; i++)
{
if (L.elem[i] != item)
{
L.elem[j] = L.elem[i];
j++;
}
}
L.length = j;
}
int main()
{
SqList L;
int item;
InitList(L);
printf("Please input the value of item is:");
scanf_s("%d", &item);
ListDelete(L, item);
printf("After Deletion: ");
for (int i = 0; i < L.length; i++)
{
printf("%d ", L.elem[i]);
}
return 0;
}