单链表练习题-删除有序单链表中的重复元素(C语言实现)

练习题-删除有序单链表中的重复元素(C语言实现)

一、题目

​ 如题所述,是对单链表进行操作,而且链表是有序的,意味着重复元素都是挨在一块儿的,如下图所示:

image-20211006172050861

​ 或者是这样的:

image-20211006172340409

二、思路

​ 既然重复元素都是连续挨着的,那么我们可以设置一个快慢指针,用temp指向上一个元素的值,p指向当前元素,如果p所指和temp所指元素相等,那么把p所指的结点删除,temp保持不动,p指针后移;如果p所指和temp所指元素不等,那么temp向后移动,即temp等于p,然后再把p后移,直到p指向单链表的末尾。如下图:

image-20211006174032607

三、代码实现

bool Del_duplicate(LinkList *B)
{
	LinkList *q,*temp;
	q = B->next;
	temp = q;//temp是慢指针,指向q的前驱 
	
	q = q->next;//q往后移动 
	
	while(q->next!=NULL)
	{
		if(q->data == temp->data)//如果p当前指向的元素和前面的结点元素相同则删除p所指结点 
			temp->next = q->next;//执行删除操作 
		else
			temp = q;//如果不等则更新temp,并且p继续向后移动,直到链表末尾 

		q = q->next;//q向后移动 
	}
	return true;
} 

​ 这种方法实现显然比较简单,当然也还有别的方法,但是我这种方法空间复杂度为O(1),时间复杂度也只是为O(n),也还算不错了。

四、全部代码

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h> //根据C99标准,C语言使用bool类型需要添加这个头文件

typedef int ElemType;

typedef struct LinkNode
{
	ElemType data;
	struct LinkNode *next;
}LinkList;

//------------ 函数声明 ----------//
void MainMenu();
bool InitLinkList(LinkList *B);//初始化 
bool InsertLinkList(LinkList *B,ElemType e);//插入
void PrintAll(LinkList *B);//输出所有元素 
bool Del_duplicate(LinkList *B);//删除重复元素 
//------------ 函数声明 ----------//


int main()
{
	LinkList B;
	
	int ch; 
	ElemType element;
	
	if(InitLinkList(&B))
		printf("初始化成功!\n");
	else
		printf("初始化失败!\n");
	
	while(1)
	{
		MainMenu(); 
		printf("请输入您要执行的操作:");
		scanf("%d",&ch);
		
		switch(ch)
		{
			case 0:		printf("感谢使用,已退出!");	exit(0);	break;
			case 1:		printf("请输入您要插入的元素:\n");
						scanf("%d",&element); 
						if(InsertLinkList(&B,element))
							printf("插入成功!\n");
						else
							printf("插入失败!\n");
						break;
			case 2:		PrintAll(&B);
						break;		
			case 3:     if(Del_duplicate(&B))
							printf("删除成功!\n");
						else
							printf("删除失败!\n");
						break; 
			default:	printf("您输入的操作指令有误!请重新输入!");
		}
	}
	
	return 0;
}

//主菜单,显示 
void MainMenu()
{
	printf("\n\n\n");
	printf("\t      **** 删除有序单链表中的重复元素 ****\n\n"); 
	printf("\t      -------	0.退出 \n\n");
	printf("\t      -------	1.插入元素\n\n");
	printf("\t      -------	2.输出所有元素\n\n");
	printf("\t      -------	3.删除重复元素\n\n");
	printf("\t      *************************************\n");
}


//初始化单链表(带头结点) 
bool InitLinkList(LinkList *B)
{
	//先申请一个头结点
	LinkList *head = (LinkList *)malloc(sizeof(LinkList));

	B->next = head;
	head->next = NULL;//头结点之后一开始还没元素
	return true;
} 

//插入
bool InsertLinkList(LinkList *B,ElemType e)
{
	//头插法
	LinkList *p = B;//
	
	//申请一个新的结点
	LinkList *s = (LinkList *)malloc(sizeof(LinkList));
	
	s->data = e;//赋值 
	
	//修改指针  将结点s插入到结点p之后 
	s->next = p->next;//s指针指向
	p->next = s;

	return true;
} 


void PrintAll(LinkList *B)
{
	LinkList *q;
	q = B->next;

	//打印出所有元素 
	while(q->next!=NULL)
	{
		printf("%d ",q->data);
		q = q->next;
	}
}

bool Del_duplicate(LinkList *B)
{
	LinkList *q,*temp;
	q = B->next;
	temp = q;//temp是慢指针,指向q的前驱 
	
	q = q->next;//q往后移动 
	
	while(q->next!=NULL)
	{
		if(q->data == temp->data)//如果p当前指向的元素和前面的结点元素相同则删除p所指结点 
			temp->next = q->next;//执行删除操作 
		else
			temp = q;//如果不等则更新temp,并且p继续向后移动,直到链表末尾 

		q = q->next;//q向后移动 
	}
	return true;
} 

五、测试

​ 输入得到一个序列:

image-20211006174827701

​ 执行删除操作之后再查看结果:

image-20211006174906510

​ 结束。

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个用单链表删除重复元素C语言代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; } Node, *LinkedList; LinkedList createList(int n); // 创建单链表 void printList(LinkedList list); // 输出单链表 void deleteDuplicates(LinkedList list); // 删除重复元素 int main() { int n; LinkedList list; printf("请输入单链表元素个数:"); scanf("%d", &n); list = createList(n); printf("原始单链表:"); printList(list); deleteDuplicates(list); printf("删除重复元素后的单链表:"); printList(list); return 0; } LinkedList createList(int n) { int i, data; Node *head, *p, *q; head = (Node *)malloc(sizeof(Node)); head->next = NULL; q = head; for (i = 0; i < n; i++) { printf("请输入第%d个元素:", i + 1); scanf("%d", &data); p = (Node *)malloc(sizeof(Node)); p->data = data; p->next = NULL; q->next = p; q = p; } return head->next; } void printList(LinkedList list) { Node *p = list; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } void deleteDuplicates(LinkedList list) { Node *p = list, *q, *r; while (p != NULL) { q = p; while (q->next != NULL) { if (q->next->data == p->data) { r = q->next; q->next = r->next; free(r); } else { q = q->next; } } p = p->next; } } ``` 这个代码,我们首先定义了一个`Node`结构体,表示单链表的节点,其包括数据成员`data`和指向下一个节点的指针`next`。然后,我们定义了一个`LinkedList`类型,表示单链表。`createList`函数用来创建单链表,它接收一个参数`n`,表示单链表元素个数。在函数内部,我们先创建一个头节点`head`,然后通过循环读入用户输入的元素,并创建一个节点`p`,把它插入到链表的尾部。最后,返回头节点的下一个节点,即为创建好的单链表。 `printList`函数用来输出单链表的所有元素,它接收一个参数`list`,表示要输出的单链表。在函数内部,我们通过循环遍历单链表的每个节点,依次输出它的数据成员`data`。 `deleteDuplicates`函数用来删除单链表重复元素,它接收一个参数`list`,表示要处理的单链表。在函数内部,我们通过两重循环遍历单链表的每个节点,如果发现有重复元素,则删除后面的那个节点。具体来说,我们用指针`p`遍历单链表的每个节点,用指针`q`遍历从`p`开始的后面的节点。如果发现`q`指向的节点的数据成员`data`与`p`指向的节点相同,则删除`q`指向的节点,否则,继续往后遍历。这样,当所有的`q`节点都遍历完后,我们再把`p`指向下一个节点,继续遍历。最终,所有的重复元素都被删除了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值