链表:逆置单向头结点链表,删除链表相同元素【C语言,数据结构】(内含源代码)

目录

实验题目:

题目分析:

尾插法:

删除相同:

就地逆置链表:

源代码:

 小结:


实验题目:

设计并验证以下算法:判定带头节点单向链表L的数据元素是否为非递增有序。如果是非递增有序的,删除值相同的多与元素,并就地逆置删除后的链表L;如果不是非递增有序的,输出相应的提示。

1.根据键盘输入数据,用尾插法建立带头节点的单向链表L。

2输出带头结点单向链表L,删除值相同多与元素后的单向链表L,就地逆置后的电箱链表L。

题目分析:

1.要求使用尾插法建立链表

2.输入可能有序,可能无序,需要判断有无序,并给出结果

3.删除相同元素,要在原表上。

3.逆置链表,要在原表上

尾插法:

什么是尾插法?简单点说

就是,链表的最后一个元素为NULL,把这个NULL替换成新的元素,就是尾插法。

用图说就是:

74a872d586f34969a6f2c624806ad0a2.png

NULL是链表的最后一个元素,替换就行。

删除相同:

怎么删除相同呢?

这里有一种思路是:

用两个指针,分别指向前一个,和后一个,如果前后两个相等,则删除后面的一个。

至于链表的删除操作,属于链表的基本操作,在这里就不多讲了,可以看教材或查阅资料

058dfca2e1ba43ab82132ab0aff0bd83.png

就地逆置链表:

这里的方法是:

从头结点开始,往下走,不停的把链表的指针逆转。

问:就地逆置链表要用几个工具指针?

答案是三个,为什么?

26a473388a394a578f47918ee20dc94a.png

 这是两个指针,我现在需要把第二个指向前一个,当我改变第二个指针的朝向时,它的指针就丢失了下一个节点的指向。如果我要把我的工具指针指向下一个节点,已经不可能了。

所以我们需要第三个指针来帮助我们记住下一个节点的位置。

源代码:

头文件:

#include <stdio.h> 			//头文件
#include <stdlib.h>
#include <malloc.h>
#include <conio.h>
#include <string.h>
#define ERROR 0
#define OK 1	//函数结果状态代码
#define EQUAL 1
#define OVERFLOW -1
typedef int Status;	//Status 为函数返回值类型,其值为函数结果状态代码
struct NUBMER {
	int nub;
} stu[50];
typedef struct NUBMER ElemType;
//链表中数据元素类型
struct LNODE {
	ElemType data;
	struct LNODE *next;
};
typedef struct LNODE LNode;
typedef struct LNODE *LinkList;//线性表的链式存储结构的定义

Status InitList_LinkList(LinkList *); //带头结点单向链表L的初始化
Status GetElem_LinkList(LinkList, int, ElemType *);//获取链表L第i个元素
int ListLength_LinkList(LinkList);//求链表 L的长度
int EqualList(ElemType, ElemType); //判断数据元素 e1、e2是否相等
int LocateElem_LinkList(LinkList, ElemType, int);//在链表L中寻找第一个与
int Less_EqualList(ElemType, ElemType);//判断数据元素 el 是否小于 e2数据元素 e符合 type 关系的元素
Status ListInsert_LinkList(LinkList, int, ElemType);//在链表L的第 i个元素前插入新元素 e
void MergeList_LinkList(LinkList, LinkList, LinkList *); //例 2.2 已知单链线性
//表 La 和 Lb 的元素按值非递减排列,归并后得到新的单链线性表 Lc,元素也按值非递减排列
Status Destroy_LinkList(LinkList *);//销毁一张链表
void printlist_LinkList(LinkList); //输出链表L

Status InitList_LinkList(LinkList *L) { //带头结点单向链表L的初始化
	*L=(LNode *)malloc(sizeof(LNode));
	if(!L)
		exit(ERROR);
	(*L)->next=NULL;
	return OK;
}//InitList_LinkList
int ListLength_LinkList(LinkList L) { //求链表L的长度
	int j=0;
	while (L->next) {
		L=L->next;
		j++;
	}
	return j;
}//ListLength_LinkList
Status GetElem_LinkList(LinkList L, int i, ElemType *e) { //获取链表L的第i个元素
	LinkList p;
	int j;
	p=L->next;
	j=1;
	while (p&&j<i) {
		p=p->next;
		++j;
	}
	if(!p||j>i)
		return ERROR;
	*e=p->data;
	return OK;
}//GetElem_LinkList


Status ListInsert_LinkList(LinkList L, int i, ElemType e) { //在链表 L的第i个元素前插入新元素。
	LinkList p, s;
	int j;
	p=L;
	j=0;
	while (p&&j<i-1) {
		p=p->next;
		++j;
	}
	if(!p||j>i-1) return ERROR;
	s=(LinkList)malloc(sizeof(LNode));
	s->data=e;
	s->next=p->next;
	p->next=s;
	return OK;
}//ListInsert_LinkList
Status Destroy_LinkList(LinkList *L) { //销毁一张链表
	LinkList p, q;
	p=*L;
	q=p->next;
	while (p) {
		free(p);
		p=q;
		q=q->next;
	}
	return OK;
}//DestroyQueue

void printlist_LinkList(LinkList L) { //输出链表L
	int i;
	LinkList p;
	p=L;
	while (p->next) {
		p=p->next;
		printf("%d ", p->data.nub);
	}
	printf("\n");
}//printlist_LinkList

主函数:

#include "LinkList.h"	//头文件

Status Reverse_LinkList(LinkList *);	//逆转一张链表
Status DeleteSame_LinkList(LinkList);	//删除相同元素
void JudgeOrder_LinkList(LinkList);	//判断是否为非递增有序
void input(LinkList);		//根据输入创建

//*****main*****
int main() {
	
	
	LinkList La;
	InitList_LinkList(&La);	//原链表
	
	input(La);

	printf("Original LinkList: ");
	printlist_LinkList(La);

	JudgeOrder_LinkList(La);

	printf("\nDeduplicated LinkList: ");
	DeleteSame_LinkList(La);
	printlist_LinkList(La);

	printf("\nReverse LinkList: ");
	Reverse_LinkList(&La);
	printlist_LinkList(La);

}//main

void input(LinkList La){		//根据输入创建
	int n;
	ElemType e;
	
	printf("How long the LinkList will you take?\n");
	scanf("%d",&n);

	printf("Please input some integers to fill the LinkList.\n");
	for(int i = 1; i<=n; i++) {
		scanf("%d",&e.nub);
		ListInsert_LinkList(La, i, e);
	}
}//input

void JudgeOrder_LinkList(LinkList L) {	//判断是否为非递增有序
	LinkList p = L->next;
	while(p->next) {
		if(p->data.nub < p->next->data.nub) {
			printf("\nNot in order\n");
			exit(0);
		}
		p = p->next;
	}
}//JudgeOrder_LinkList

Status Reverse_LinkList(LinkList *L) {	//逆转一张链表
	LinkList h,p,q,r;
	h = *L;
	q = h->next;
	if(!q->next){
		return OK;
	} 
	p = q->next;
	q->next = NULL;
	while(p->next) {
		r = q;
		q = p->next;
		p->next = r;
		r = p;
		p = q;
		q = r;
	}
	h->next = p;
	p->next = q;

	return OK;
}	//Reverse_LinkList

Status DeleteSame_LinkList(LinkList L) {	//删除相同元素
	LinkList q, p;
	q = L->next;
	while(q->next) {
		p = q->next;
		if(q->data.nub == p->data.nub) {
			q->next = p->next;
		} else {
			q = p;
		}
	}
	return OK;
}	//DeleteSame_LinkList

小结:

该题目还是比较基础的,如果做不出来的话,可以尝试画图来推导指针是怎么走的。

通过画图带动抽象思维。

加油,一起努力↖(^ω^)↗

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值