数据结构与算法——线性表的链式实现

目录

 一、前言 

二、头文件

三、各种功能的实现

四、主函数测试结果


 一、前言

        上一章我们写了线性表的顺序存储结构,应该也可以理解为一种静态数据结构(Static Data Structure),即事先分配好空间,在逻辑上相邻的两个元素在物理位置上也相邻,可以随机存取任意元素,在插入、删除操作时,需要大量移动元素,且效率低下。因此本章来写写另一种结构,动态数据结构(Dynamic Data Structure),也叫线性表的链式存储结构——单链表

二、头文件

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int ElemType;//重命名

//-----------线性表的单链表存储结构-----------
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LNode, *LinkList;

void Init_LinkList(LinkList *head);//初始化
void Create_LinkList(LinkList *head);//创建链表
void Show_LinkList(LinkList *head);//显示链表(遍历)
int Length_LinkList(LinkList *head);//链表长度
void Insert_LinkList(LinkList *head, ElemType x, int pos);//按位置插入元素
void Delete_LinkList(LinkList *head, int pos);//按位置删除元素
void Sort(LinkList *head);  //排序法(非递减)
void Merge_LinkList(LinkList p1, LinkList p2, LinkList *p3);//合并两个链表

void Reverse(LinkList *head);//单链表逆置(递归)
LNode* Reverse(LNode *p);  //相当于给了个封装

//-------------  排序算法以后会优化  ---------------

三、各种功能的实现

1、初始化

//初始化
void Init_LinkList(LinkList *head)
{
	*head = (LinkList)malloc(sizeof(LinkList));
	assert(*head != NULL);
	(*head)->next = NULL;
}

2、创建链表

//创建链表
void Create_LinkList(LinkList *head)
{
	LNode *p = *head;

	int item;
	printf("请输入数据(以-1结束):");
	while (scanf("%d", &item) ,item != -1)
	{
		LNode *s = (LNode*)malloc(sizeof(LNode));
		assert(s != NULL);
		s->next = NULL;

		s->data = item;
		p->next = s;
		p = s;
	}

}

 3、遍历

//显示链表(遍历)
void Show_LinkList(LinkList *head)
{
	LNode *p = (*head)->next;
	while (p)
	{
		printf("%d->", p->data);
		p = p->next;
	}
	printf("NULL.\n");
}

4、求长度

//链表长度
int Length_LinkList(LinkList *head)
{
	LNode *p = (*head)->next;
	int i = 0;
	while (p)
	{
		p = p->next;
		i++;
	}
	return i;
}

 5、按位置插入

//按位置插入元素
void Insert_LinkList(LinkList *head, ElemType x, int pos)
{
	LNode *p = *head;   //在单链表的pos位置之前插入元素x
	int i = 0;

	while (p&&i < pos - 1)  //寻找位置pos-1
	{
		p = p->next;
		i++;
	}
	if (!p || i>pos - 1)
	{
		printf("插入位置非法...\n");
		return;
	}

	LNode *s = (LNode*)malloc(sizeof(LNode));
	assert(s!= NULL);
	s->data = x;
	s->next = p->next;
	p->next = s;
}

6、按位置删除

//按位置删除元素
void Delete_LinkList(LinkList *head, int pos)
{
	LNode *p = *head;
	int i = 0;

	while (p&&i < pos - 1)  //寻找位置pos-1
	{
		p = p->next;
		i++;
	}
	if (!p || i>pos - 1)
	{
		printf("插入位置非法...\n");
		return ;
	}

	LNode *q = p->next;
	p->next = q->next;
	free(q);
}

 7、非递减排序

//排序(非递减)
void Sort(LinkList *head)
{
	LNode *p, *q;
	p = (*head)->next;
	if (p != NULL)
	{
		q = p->next;
	}
	else
	{
		printf("无法进行排序...\n");
		return;
	}

	for (p; p != NULL; p = p->next)
	{
		for (q; q != NULL; q = q->next)
		{
			if (p->data > q->data)
			{
				int temp = p->data;
				p->data = q->data;
				q->data = temp;
			}
		}
		q = p->next;
	}
}

8、合并两个单链表

//合并两个单链表
void Merge_LinkList(LinkList p1, LinkList p2, LinkList *p3)
{
	//Sort(&p1); //以非递减排序单链表
	//Sort(&p2); //以非递减排序单链表

	LNode *pa, *pb, *pc;
	pa = p1->next;
	pb = p2->next;
	pc = *p3;
	while (pa&&pb)
	{
		if (pa->data > pb->data)
		{
			pc->next = pb;
			pc = pb;
			pb = pb->next;
		}
		else
		{
			pc->next = pa;
			pc = pa;
			pa = pa->next;
		}
	}
	pc->next = pa ? pa : pb;//插入剩余段
}

 9、单链表逆置(递归)

//单链表逆置(递归)
void Reverse(LinkList *head)
{
	LNode *p = *head;
	while (p->next)
	{
		p = p->next;  //过去最后一个结点
	}

	Reverse((*head)->next);
	(*head)->next->next = NULL;
	(*head)->next = p;
}
LNode* Reverse(LNode *p)
{
	if (p == NULL || p->next == NULL)
	{

		return p;   //找到最后一个结点
	}
	LNode *s = Reverse(p->next);

	s->next = p;  //将结点的指向反向
	p->next = NULL;

	return p;
}

四、主函数测试结果

int main()
{
	LinkList List_1, List_2, List_3;
	Init_LinkList(&List_1);
	Init_LinkList(&List_2);
	Init_LinkList(&List_3);

	printf("表1:");
	Create_LinkList(&List_1);
	printf("表2:");
	Create_LinkList(&List_2);
	printf("\n表1:");
	Show_LinkList(&List_1);
	printf("表2:");
	Show_LinkList(&List_2);

	Sort(&List_1); //以非递减排序单链表
	Sort(&List_2); //以非递减排序单链表
	printf("\n排序后:\n");
	printf("表1:");
	Show_LinkList(&List_1);
	printf("表2:");
	Show_LinkList(&List_2);

	printf("\n合并单链表:");
	Merge_LinkList(List_1, List_2, &List_3);
	Show_LinkList(&List_3);

	printf("\n按位置插入(pos=4,x=20):");
	Insert_LinkList(&List_3,20,4);
	Show_LinkList(&List_3);

	printf("\n按位置删除(pos=4):");
	Delete_LinkList(&List_3, 4);
	Show_LinkList(&List_3);

	printf("\n单链表逆置:");
	Reverse(&List_3);
	Show_LinkList(&List_3);

	printf("\n长度:");
	int len = Length_LinkList(&List_3);
	printf("%d", len);

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leisure-pp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值