/* 2.3 链表*/
//第一题代码:删除不带头结点单链表L中的所有值为x的结点 (要求递归算法)
void List_datax(LinkList &L, int x){
LNode *p;
if(L == NULL)
return;
if(L ->data == x){
p = L; //代替指针,保留释放位置
L = L -> next; // 向前遍历
free(p);
List_datax(L,x); //进行下一次递归
}
else{
List_datax(L -> next,x); //该L指针对应数字不等于x,向后遍历
}
}
//第二题代码:带头结点单链表L,删除x值结点
void det_x(LinkList &L, int x){
LNode *p = L -> next, *tag = 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 r_print(LinkList L){
//与题5一样
}
//第四题代码:单链表L删除最小值
void min_L(LinkList &L){
LNode *pre = L, *p = L -> next;
LNode *minpre = pre, *min = p;
while(p != NULL){
if(p -> data < min -> data){
min = p;
minpre = pre;
}
pre = p;
p = p -> next;
}
minpre -> next = min -> next;
free(min);
return L;
}
//第五题代码:带头结点单链表就地逆置
struct ListNode* reverseList(struct ListNode* L){
struct ListNode *p, *r;
p = L -> next; //p是遍历函数
L -> next = NULL; //置空链
while(p != NULL){
r = p -> next; //保存指向下一个结点
p -> next = L -> next; //头插入
L -> next = p;
p = r;
}
return L;
}
//法二
struct ListNode* reverseList(struct ListNode* L){
struct ListNode *p, *r = L -> next,*k = r -> next;//三个指针第一个防止断链,第二个遍历,第三个充当后面元素结点
r -> next = NULL;
while(k != NULL){
p = r;
r = k;
k = k -> next;
r -> next = p;
}
L -> next = r;
return L;
}
//第6题代码:带头结点L,让元素递增有序
void zheng_L(LinkList &L){
LNode *q = L -> next,*pre;
LNode *r = p -> next; //防止断链
q -> next = NULL;
q = r;
while(p != NULL){
r = p -> next;
pre = L;
while(pre -> next != NULL && pre -> next -> data < p -> data) //双循环里面的判断,下一个不为零且p指针数据要大进行遍历
pre = pre -> next;
p -> next = pre -> next; //就是一个插入操作
pre -> next = p;
p = r;
}
}
//第七题代码:L无序,删除给定的俩值范围
bool ding_L(LinkList &L,int m,int n){
zheng_L(L); //让元素递增有序
LNode *q = L,*p;
while(q -> next -> data > m){
q = q -> next;
}
while(q -> next != NULL && q -> next -> data <=n){
p = q -> next;
q -> next = p -> next;
free(p);
}
return true;
}
//法二
void ding_L(LinkList &L,int min, int max){
LNode *pr = L,*p = L -> next; //pr为前一个结点 p为炮灰结点
while(p != NULL){
if(p -> data < min && p -> data > max){
pr -> next = p -> next;
free(p);
p = pr -> next;
}
else{
pr = p;
p = p -> next;
}
}
}
// 第八题 两个链表的公共部分
//整体思路比较俩链表的长度然后长表遍历到与短表长度相等,找到第一个相等点即可返回公共部分;
LinkList Search_lest_common(LinkList &L1, LinkList &L2){
int dist;
int len1 = Length(L1), len2 = Length(L2); //俩表长度
LinkList longlist,shortlist; //分别指向长表与短表
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 == shortlist) //找到第一个共同结点
return longlist;
else{
longlist = longlist -> next;
shortlist = shortlist -> next;
}
}
return NULL;
}
//第九题 头结点为head递增输出且释放结点
void sq_printf(LinkList &L){
while(head -> next == NULL){
LNode *q = head; //记录前驱
LNode *p = q -> next; //工作结点
LNode *u; //炮灰结点用于free
while(p -> next != NULL){
if(p -> next ->data < q - next -> data){
q = p; //记住当前最小前驱
}
p = p -> next;
}
printf(q -> next -> data);
u = q -> next;
q -> next = u -> next;
free(u);
}
free(head);
}
// 第10题 链表一分为二 一个保留奇数一个保留偶数
void split_list(LinkList &L){
int count = 0;
LinkList K = (LinkList) malloc (sizeof(LNode));//创建K表表头
K -> next = NULL; //K表初始化
LNode *pre = L; //指向表头准备接客(为奇数的结点)
LNode *q = L -> next; //
LNode *u = K; //指向表头准备接客(为偶数的结点)
while(q != NULL){
count++;//记录判断结点
if(count % 2 == 0){
u -> next = q; //插入新节点
u = q; //准备接下一个
}
else {
pre -> next = q;
pre = q;
}
q -> next = q;
}
u -> next = NULL;
pre -> next =NULL;
return K;
}
//第11题
void list_Linklist(LinkList &A){
LinkList *B = (LinkList) malloc (sizeof(LNode));
B -> next = NULL;
LNode *p = A -> next,*q; //p为工作结点 q防止断链
LNode *ra = A; //p的前驱结点
while(p != NULL){
ra -> next = p; ra = p;
p = p -> next;
q = p -> next;
p -> next = B -> next;
B -> next = p;
p = q;
}
ra -> next = NULL;
return B;
}
//第12题在递增有序单链表去除不重复元素
void fold_List(LinkList &L){
LNode *q = L -> next; *p;
if(p == NULL)
return -1;
while(p -> next != NULL){
q = p -> next; //待定删除元素
if(p -> data == q -> data){
p -> next = q -> next; //跳过了q所指结点
free(q);
}
else
p = p -> next;
}
}
//第13题 两个按元素值递增次序排列,合并为一个按元素值递减次序的
//函数的合并
void merge(LinkList &L1,LinkList &L2){
LNode *p1 = L1 -> next,*p2 = L2 -> next,*t;
L1 -> next = NULL;
while(p1 && p2){
if(p1 -> data <= p2 -> data){
t = p1 -> next;
p1 -> next = L1 -> next;
L1 -> next = p1;
p1 = t;
}
else{
t = p2 -> next;
p2 -> next = L1 -> next;
L1 -> next = p2;
p2 = t;
}
}
/*if(p1) p2 = p1;*/ //同样的功能
while(p1){
t = p1 -> next;
p1 -> next = L1 -> next;
L1 -> next = p1;
p1 = t;
}
while(p2){
t = p2 -> next;
p2 -> next = L1 -> next;
L1 -> next = p2;
p2 = t;
}
free(L2);
}
//找公共元素
void common_list(LinkList L1,LinkList L2,LinkList &L){
L = (LinkList) malloc (sizeof(LNode));
L -> next = NULL;
LNode *q = L1 -> next,*p = L2 -> next,*s;
while(q && p){
if(q -> data < p -> data){
q = q -> next;
}
else if (q -> data == p -> data){
s = (LNode *) malloc (sizeof(LNode));
s -> data = q -> data;
s -> next = L -> next;
L -> next = s;
q = q -> next;
p = p -> next;
}
else if(q -> data > q -> data)
p = p -> next;
}
}
//第15道题两个递增链表,求俩链表的交集存放A链中
LinkList Union(LinkList &L1, LinkList &L2){
LNode *pa = L1 -> next;
LNode *pb = L2 -> next;
LNode *u,*pc = L1;
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(L2);
return L1;
}
//判断序列B是否是序列A的连续序列
bool contiune(LinkList &L1, LinkList &L2){
LNode *pa = L1 -> next;
LNode *pb = L2 -> next;
LNode *pre = pb;
while(pb && pa){
if(pa -> data == pb -> data){
pa = pa -> next;
pb = pb -> next;
} else{
pre = pre -> next;
pb = pre;
pa = L1 -> next;
}
}
if(pa == NULL){
return true;
}else return false;
}
//第17题 判断循环双链表是否对称
void contrary(DLinkList L){
LNode *q = L -> next;
LNode *p = L -> prior;
while(p -> next != q && q != p){
if(p -> data == q ->data){
q = L -> next;
p = p -> prior;
}else return 0;
}
return 1;
}
//第18题 两个循环指针合并后依然是循环
void Union_d(DLinkList &L1, DLinkList &L2){
LNode *q = L1,*p = L2;
LNode *h1 = L1 -> next;
LNode *h2 = L2 -> next;
while(h1 -> next != q){
h1 = h1 -> next;
}
h1 -> next = h2;
h2 -prior = h1;
while(h2 -> next != p){
h2 = h2 -> next;
}
h2 -> next = q;
q - prior = h2;
return L1;
}
//第19题 循环单链表反复找出最小值删除直到为空
void Ddete(DLinkList &L){
LNode *p,*pre;
LNode *q,*qre;
while(L -> next != L){
p = L -> next; pre = L;
qre = L;q = p;
while(p != L){
if(p -> data < p -> data){
q = p;
qre = pre;
}
pre = p;
p = p -> next;
}
printf("%d",q -> data);
qre -> next = q -> next;
free(q);
}
free(L);
}
//第20题 难懂
void Locate(DLinkList &L, ElemType x){
DNode *p = L -> next,*q; //p遍历数组
while(p && p -> data != x){ //找到值为X的数
p = p -> next;
if(!p)
exit(0);
else{
p -> freq++; //访问频度域指针加一
if(p -> pre == L || p -> pre -> freq > p -> freq) //如果p是第一个结点或者p的访问频度要小于前一位(q -> pre)则返回
return p;
if(p -> next != NULL) //p为最后一个值不需要下面这一步
p -> next -> pre = p -> pre;
p -> pre -> next = p -> next;//先把p结点摘下来
q = p -> pre; //查找p结点合适的插入位置
while(q != L && q -> freq <= p -> freq) //遍历寻找
q = q -> pre;
p -> next = q -> next;//q遍历到符合点的前一位
if(q -> next != NULL) q -> next -> pre = p; //将p结点排在同频率的第一个
p -> pre = q;
q -> next =p;
}
return p;
}
}
//第21题 判断单链表是否有环
LNode* FindLoopStart(LNode *head){
LNode *fast = head, *slow = head;
while(fast != NULL && slow -> next != NULL){
fast = fast -> next -> next;
slow = slow -> next -> next;
if(slow == fast)
break;
}
if(fast == NULL || slow -> next == NULL)
return NULL;//没有环返回
LNode *p1 = head, *p2 = slow;//分别指向开始和相遇点
if(p1 != p2){
p1 = p1 -> next;
p2 = p2 -> next;
}
return p1;//返回人口点
}
//第22题 输出倒数第k个位置
void reverse_k(LinkList L,int k,int &a){
LNode *q = L;
int len = 0;
while(q -> next != NULL){
q = q -> next;
len++;
}
if(k>len) return 0;
int j = len - k + 1;
q = L;
while(j >0){
j--;
q = q -> next;
}
a = q -> data;
}
//法二
LNode *
//第23题 单链表有相同的后缀找出后缀点q
//解题思路:len()俩链表的长度,然后用for循环对齐,之后遍历到俩链表指针相等的时候
LinkNode *Find_1st_Common(LinkList str1, LinkList str2){
int len1 = length(str1), len2 = length(str2);
LNode *q,*p;
for(p = str1; len1>len2; len2--)//指向的位后面大小相同
p = p -> next;
for(q = str2; len2>len1; len1--)
q = q ->next;
while(p -> next != NULL && p -> next != q -> next){
p = p -> next;
q = q -> next;
}
return p -> next;//返回起点
}
//第24题 删除绝对值相等的点,只留一个
对于 `*(str + i)`的解释
在C语言中,`*(str + i)`表示对指针的操作。
假设`str`是一个指向字符数组的指针,`i`是一个整数。`*(str + i)`表示取指针`str`偏移`i`个位置处的字符值。
下面是一个示例代码,演示了如何使用`*(str + i)`获取字符数组中的特定字符:
```c
#include <stdio.h>
int main() {
char str[] = "Hello World";
int i = 6;
char c = *(str + i);
printf("The character at index %d is: %c\n", i, c);
return 0;
}
```
在上述代码中,我们有一个字符数组`str`,包含字符串"Hello World"。我们使用`*(str + i)`来获取字符数组中索引为`i`的字符,然后打印它。
当`i`的值为6时,输出结果为:"The character at index 6 is: W",表示在索引为6的位置上,字符数组中的值为字符'W'。
请注意,C语言中的指针操作需要小心处理,确保不会越界访问数组或悬空指针。
void func(LinkLink &L, int n){
LNode *q = h,r;
int *q,m;
q = (int*) malloc (sizeof(int) * (n+1));
for(int i = 0; i < n+1; i++)
*(q + i) = 0;//数组全为零
while(p -> next != NULL){
m = p -> next -> data>0 ? p -> next -data : -p -> next -> data;
if(*(q + m) == 0){
*(q + m) = 1;
p = p -> next;
}
else{
r = p -> next;
p -> next = r -> next;
free(r);
}
}
free(q);
}
//第25题 后半段逆置然后交叉插入
int change_list(LinkList &L){
LNode *q = L,*q = L;
LNode *r,*s;
while(q -> next != NULL){
p = p -> next; //走一步
q = q -> next;
if(q -> next != NULL)
q = q -> next;//走两步
}
q = p -> next; //q为后半段链首
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;
}
}
王道24数据结构第二章链表代码题
最新推荐文章于 2024-10-18 16:39:57 发布
本文提供了多种链表操作的C语言实现,包括删除特定值的节点、删除指定范围内的节点、链表反向输出、删除最小值、链表逆置、保持递增顺序、删除重复元素、合并两个链表等。这些算法涉及链表的基本操作和复杂操作,如递归、双指针和排序技巧。
摘要由CSDN通过智能技术生成