考研数据结构之线性表(1.7)——练习题之删除单链表的最小值结点(C表示)

题目

设计一个算法删除单链表L(有头结点)中的一个最小值结点。

分析

先谈谈我自己写的思路:(1)寻找到最小值结点,返回最小值结点的指针或者返回最小值结点在链表中的序号位置;(2)删除指定位置的最小值结点。

关于寻找链表中的最小值结点,可以先考虑将链表的开始结点(第一个结点)设置为最小值结点,然后将最小值结点与链表中的每个结点进行比较,如果比最小值结点小的话,就将该结点置为最小值结点,反之继续比较,最后返回。

核心代码如下:

/* 在单链表中查找结点元素data值最小的结点 */
/* *list指的是要查找最小值结点的链表 */
LNode * findMin(LNode *list) {
	LNode *temp=list->next; // 开始结点
	LNode *min=list->next; // 最小值结点,意思是将开始结点设置为最小值结点
	while(temp!=NULL) { // 循环条件,当head!=NULL时
		if(temp->data<min->data) { // 比较当前结点的数据与最小值结点的数据
			min=temp; // 如果小于最小值的结点的数据,那么就将该结点设置为最小值结点
		}
		temp=temp->next; // 循环到下一个结点
	}
	return min; // 返回最小值结点
}

/* 删除单链表中最小值结点 */
/* *list指的是要操作的单链表;*minNode指的是要被删除的最小值结点 */
void deleteMinNode(LNode *list,LNode *minNode) {
	LNode *temp=list->next;// 开始结点,即第一个结点
	LNode *pre=list; // 头结点
	LNode *tempDelNode; // 临时保存要被删除的结点
	while(temp!=NULL) { // 循环遍历单链表中的所有结点
		if(temp->data==minNode->data) { // 比较当前结点与最小结点的值是否相等,如果相等,则删除当前结点,否则继续寻找下一个
			tempDelNode=temp; // 临时保存要被删除的最小值结点
			pre->next=tempDelNode->next;// 将头结点指向被删除结点的下一个结点,实现删除操作连接新链表
			free(tempDelNode); // 释放结点资源
			break; // 跳出循环
		} else { // 如果不相等,就去下一个结点进行判断
			pre=temp; // 记录终端结点指向temp
			temp=temp->next; // 到单链表的下一个结点
		}
	}

}

完整代码如下:

#include <stdio.h>
#include <stdlib.h>
// 声明单链表结构体
struct LNode {
	int data;
	struct LNode *next;
};

/* 通过用户输入数据创建一个单链表,由用户输入整型测试数据 */
/* 返回一个单链表 */
LNode * createList() {
	LNode *head;
	LNode *p1,*p2;
	p1=p2=(LNode *)malloc(sizeof(LNode));
	head=(LNode *)malloc(sizeof(LNode));
	scanf("%ld",&p1->data);
	int i=0;
	while(p1->data!=0) { // 当用户在控制台输入0时结束循环
		i+=1;
		if(i==1) {
			head->next=p1;
		} else {
			p2->next=p1;
		}
		p2=p1;
		p1=(LNode *)malloc(sizeof(LNode));
		scanf("%ld",&p1->data);
	}
	p2->next=NULL;
	return head;
}

/* 打印单链表 */
/* *list指的是要被打印输出的单链表 */
void printList(LNode *list) {
	LNode *temp=list->next;// 单链表的开始结点
	printf("\n");
	while(temp!=NULL) { // 循环单链表
		printf("%ld\t",temp->data); // 打印单链表中的data数据
		temp=temp->next; // 遍历至下一个结点
	}
	printf("\n"); // 换行
}

/* 在单链表中查找结点元素data值最小的结点 */
/* *list指的是要查找最小值结点的链表 */
LNode * findMin(LNode *list) {
	LNode *temp=list->next; // 开始结点
	LNode *min=list->next; // 最小值结点,意思是将开始结点设置为最小值结点
	while(temp!=NULL) { // 循环条件,当head!=NULL时
		if(temp->data<min->data) { // 比较当前结点的数据与最小值结点的数据
			min=temp; // 如果小于最小值的结点的数据,那么就将该结点设置为最小值结点
		}
		temp=temp->next; // 循环到下一个结点
	}
	return min; // 返回最小值结点
}

/* 删除单链表中最小值结点 */
/* *list指的是要操作的单链表;*minNode指的是要被删除的最小值结点 */
void deleteMinNode(LNode *list,LNode *minNode) {
	LNode *temp=list->next;// 开始结点,即第一个结点
	LNode *pre=list; // 头结点
	LNode *tempDelNode; // 临时保存要被删除的结点
	while(temp!=NULL) { // 循环遍历单链表中的所有结点
		if(temp->data==minNode->data) { // 比较当前结点与最小结点的值是否相等,如果相等,则删除当前结点,否则继续寻找下一个
			tempDelNode=temp; // 临时保存要被删除的最小值结点
			pre->next=tempDelNode->next;// 将头结点指向被删除结点的下一个结点,实现删除操作连接新链表
			free(tempDelNode); // 释放结点资源
			break; // 跳出循环
		} else { // 如果不相等,就去下一个结点进行判断
			pre=temp; // 记录终端结点指向temp
			temp=temp->next; // 到单链表的下一个结点
		}
	}

}

int main() {
	/* [0.]创建初始测试单链表 */
	LNode *list,*t1,*t2,*t3,*t4;
	LNode *list2,*mergeList;
	list=createList();// 创建测试链表
	printList(list);// 打印单链表

	t1=findMin(list); // 发现最小值结点
	printf("min=%d",t1->data);// 打印输出最大值结点的data值
	deleteMinNode(list,t1);// 删除最小值结点
	printList(list);// 打印删除后的链表

	return 0;
}

测试结果如下:

可以看出上面的代码比较多,看看参考书上的算法是怎么样的。

分析如下:用p从头至尾扫描链表,pre指向*p结点的前驱,用minp保存值最小的结点指针,minpre指向minp的前驱。一边扫描,一边比较,将最小值结点放到minp中。

代码如下:

void delminnode(LNode *L){
	LNode *pre=L,*p=pre->next,*minp=p,*minpre=pre;
	while(p!=NULL){
		if(p->data<minp->data){
			minp=p;
			minpre=pre;
		}
		pre=p;
		p=p->next;
	}
	minpre->next=minp->next; // 删除*minp结点
	free(minp); 
}

其实原理都是一样的,不过参考书上的代码确实要简洁得多。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值