数据结构代码题----Day04

数据结构代码题总结

题目01

题目描述:

设在一个带头节点的单链表中所有元素的节点的数据值无序,试编写一个函数,删除表中所有介于给定两个数值之间的元素

1、算法思路

  1. 进行删除指定条件下的节点
  2. 先查找该指定节点
  3. 删除指定节点

2、查找指定节点
以条件区间【min,max】为匹配数值进行遍历链表查找,
3、删除元素

步骤主要是:

  1. 设置一个前驱指针进行next指向当前删除指针的next
  2. free释放当前删除指针的内存
  3. 为p重新赋值

其实现代码如下:

//删除单链表中指定区间【min,max】的数据
//这里的L因为要进行删除操作,必须添加&符号,并设置为Elemtype类型
void Delete_RangeOfNode(Linklist &L,ElemType min,ElemType max){
	//初始化指针
	LNode * pre = L;//头节点赋值
	LNode * p = L->next;
	//遍历链表核心代码
	while(p != Null){
		//查找数值
		if(p->data > min && p->data < max){
			pre->next = p->next;//进行范围节点删除
			free(p);//释放内存
			p = pre->next;//为p重新初始化数值
		}else{//若没有找到
			//前驱和后继都往前移动
			pre = p;
			p = p->next;
		}
	}
}

题目02

题目描述:

给定两个单链表,编写算法找到两个单链表的公共节点

1、题目分析!!!!!!!重要

  1. 首先是看到这个题目后,大脑中构思的有公共节点的两个单链表的连接情况,无非是下面这两种:

第一种:
数据结构代码题----Day04_第1张图片
第二种:
数据结构代码题----Day04_第2张图片
下面对这两种情况进行分析:

  1. 首先是第一种情况,由于单链表的next指针域只有一个,因此只能指向一个节点第一种情况明显是违背了,
  2. 因此第一种情况是错误的

第二种情况分析:

  1. 第二种情况建立的依据便是对公共节点的进行设置,可以得到,如果单链表在遍历的过程中,找到了一个公共节点,那么剩余的节点都是公共节点。

2、算法思路分析

对于找公共节点,这里首先想到的便是遍历链表进行查找,不论有多少的节点都要进行遍历,因此遍历法也被称为暴力法
1、暴力法实现思路:

  1. 设置两个循环一个外循环用来对一条链表进行定位不动,另一个循环对另一条链表进行遍历比较。
  2. 若一条链表的一趟遍历结束了没有找到公共节点,那么其实的节点指针进行后移动。

2、算法图解如下:

数据结构代码题----Day04_第3张图片
因此其暴力法的核心便是两个循环的遍历链表,若其中的p与q对应的指针域的数据不相等,那么寻找失败
其代码实现如下:

//暴力法寻找两个单链表的公共节点
LNode * GetCommonNode(Linklist &A,Linklist &B){
	//初始化指针
	LNode * p = A->next;
	LNode * q = B->next;
	//使用双循环
	while(p != null){//外循环作为比较第一趟的结束后移
		while(q != null){
			if(p == q){//找到了公共节点
				return p;
			}else{//没有找到
				q = q->next;
			}
			//B链表全部走完一糖都没有找到公共节点
			p = p->next;//p后移
			q = B->next;//重置q的指针位置
		}
	}
	//以上的全部都没有找到公共节点
	return null;//无公共节点
}

代码分析:
1、核心操作代码:

	//使用双循环
	while(p != null){//外循环作为比较第一趟的结束后移
		while(q != null){
			if(p == q){//找到了公共节点
				return p;
			}else{//没有找到
				q = q->next;
			}
			//B链表全部走完一糖都没有找到公共节点
			p = p->next;//p后移
			q = B->next;//重置q的指针位置
		}
	}

q指针走完一趟处理:

q = q->next;

p指针操作

p = p->next;//p后移
q = B->next;//重置q的指针位置

重点:!!!结合上面的查找公共节点的代码进行时间复杂度分析,这里我们使用了双循环,因此其时间复杂度0(A链表长度*B链表长度)。这样的时间复杂度是非常大的,因此我们必须要对其进行优化代码。

下面是对当前题目的算法优化思路以及代码实现

寻找优化之路

结合题目要求对其进行反推分析:

  1. 目标要找到共节点->>>>>>>>>>同时到达表尾,
  2. 如果这个时候p==q那么这个当前节点便是公共节点
  3. 如果p!=q,也就代表着不存在公共节点
  4. 这就需要对其进行长度进行控制,如下图所示

数据结构代码题----Day04_第4张图片
这里我们对其长链表进行长度限制,以与短链表的差距节点为起始节点进行和设计。
其实现的代码如下:

//优化单链表求公共节点
LNode * GetCommonNodeByGoodNess(Linklist &A,Linklist &B){
	LNode * p ;
	LNode * q;
	//求出链表的长度
	int k = 0;//定义差值
	int A_length = GetLength(A);
	int B_length = GetLength(B);
	//对长度比大小
	if(A_length > B_length){
		k = A_length - B_length;
		p = A->next;//初始化指针
		q = B->next;
	}else{
		//B时长链
		k = B_length - A_length;
		p = B->next;
		q = A->next;//p要保证始终指向长链表
	}

	//对长链表的起始节点的位置进行调正
	while(k--){
		p = p->next;
	}

	//核心代码进行比较
	while(p != null){
		if(p == q){
			return p;
		}else{
			p = p->next;
			q = q->next;//当前的不是最后的节点,进行后移
		}
	}
	return null;//以上都没有找到
}

结合以上的代码进行时间复杂度分析,得到的时间复杂度为0(A的长度+B的长度),优化代码成功!!!!!!!!!!!!

核心代码:

//核心代码进行比较
	while(p != null){
		if(p == q){
			return p;
		}else{
			p = p->next;
			q = q->next;//当前的不是最后的节点,进行后移
		}
	}

调整代码:

int k = 0;//定义差值
	int A_length = GetLength(A);
	int B_length = GetLength(B);
	//对长度比大小
	if(A_length > B_length){
		k = A_length - B_length;
		p = A->next;//初始化指针
		q = B->next;
	}else{
		//B时长链
		k = B_length - A_length;
		p = B->next;
		q = A->next;//p要保证始终指向长链表
	}

	//对长链表的起始节点的位置进行调正
	while(k--){
		p = p->next;
	}

题目03

将一个带有头节点的单链表A分解为两个带头节点的单链表A和B,使得A表中原始的奇数序号数,B为偶数序号是数,相对位置不变

1、算法设计思路图解分析:
数据结构代码题----Day04_第5张图片
因此这里 实现过程与尾插法建立单链表类似,因此我们便有了代码设计的思路-------------尾插法

下面时一段尾插法建立单链表的代码:

//尾插法建立单链表
Listlink List_TailInsert(Linklist &L){
	LNode * s;
	L = (Linklist)malloc(sizeof(LNode));
	LNode * r = L;//指向根节点
	int x;
	scanf("%d",&x);//赋值
	while(x != -1){
		//核心代码
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		r->next = s;
		r = s;
	}
	//在最后添加后需要对为节点设置为null
	r->next = null;//设置r的下一个为null
}

下面让我们类似上面这一段代码编写解题代码:

//分割单链表
Linklist Create(Linklist &A){
	int i = 0;//节点的序号初始化
	//开辟新的链表空间
	B = (Linklist)malloc(sizeof(LNode));
	LNode * p = A->next;
	A->next = NULL;
	LNode * ra;
	LNode * rb = B;//初始化指针

	while(p != null){
		if(i % 2 == 0){//偶数
			rb->next = p;//尾插法建立单链表精髓代码
			rb = p;
		}else{//若是奇数序列
			ra->next = p;
			ra = p;
		}

		//进行遍历主链表开启下一轮循环
		p = p->next;
		i++;
	}

	//尾插法重点:
	//必须要设置最后节点为null指向
	ra->next = null;
	rb->next = null;
	return B;
}

解决!

注:

个人代码问题或需要程序编写辅导服务等问题请加闲鱼【代码无bug】
或点击下面链接跳转闲鱼进行咨询

闲鱼链接

数据结构代码题----Day04_第6张图片

你可能感兴趣的:(笔记,链表,数据结构,链表,算法)