王道24数据结构第二章链表代码题

本文提供了多种链表操作的C语言实现,包括删除特定值的节点、删除指定范围内的节点、链表反向输出、删除最小值、链表逆置、保持递增顺序、删除重复元素、合并两个链表等。这些算法涉及链表的基本操作和复杂操作,如递归、双指针和排序技巧。
摘要由CSDN通过智能技术生成
/* 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;
	} 
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值