如何实现简单链表?如何合并两个链表?(C语言实现)

目录

链表的实现:

1.先起别名,提高后续代码的开发效率,增加代码的可读性

2.定义链表结点的结构体类型

3.定义对链表的主要操作方法

4.对链表进行测试操作

测试代码总览

合并链表:

5.操作链表的方法补充:

1.合并两个链表

 2.合并两个链表,并根据其数据大小进行排序


链表的实现:

1.先起别名,提高后续代码的开发效率,增加代码的可读性

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

// C语言中,结构体类型名前的struct不可以省略!!!
// C++可以省略!


// typedef 已知类型 类型别名
typedef struct LLNode* LinkedList;  // LinkedList == struct LLNode*  链表结点指针
// --> 使用别名后,无需再写struct
typedef int elemType;  // 链表数据类型

2.定义链表结点的结构体类型

// 定义链表结点
struct LLNode
{
	elemType data;
	LinkedList next;
};

3.定义对链表的主要操作方法

// 1.初始化空链表/生成新结点
LinkedList makeEmpty()
{
	LinkedList head = (LinkedList)malloc(sizeof(struct LLNode));  // 用头指针指向申请的新空间
	head->next = NULL;
	return head;
}


// 2.查找第n个元素,返回第n个元素结点
LinkedList find_nth(int n, LinkedList head)
{
	if (n < 1)  // 输入错误
	{
		return NULL;
	}

	LinkedList p = head->next;  // 拿到第一个结点
	int i = 1;
	while (i < n && p != NULL)
	{
		p = p->next;
		i++;
	}
	if (p == NULL)  // 找不到
	{
		return NULL;
	}
	else  // 找到了
	{
		return p;
	}
}


// 3.找到值为x的元素第一次出现的位置,返回位置
int find(elemType x, LinkedList head)
{
	LinkedList p = head->next;  // 拿到第一个结点
	int count = 1;
	while (p != NULL && p->data != x)
	{
		p = p->next;
		count++;
	}
	if (p == NULL)  // 找不到值为x的元素
	{
		return NULL;
	}
	else  // 找到值为x的元素
	{
		return count;
	}
}


// 4.1在位置pos插入值为x的新结点
void insert(elemType x, int pos, LinkedList head)
{	
	if (pos < 1)  // 输入位置不符规范
	{
		printf("位置输入错误!\n");
		return;
	}

	LinkedList new_node = NULL;
	if (pos == 1)  // 插入到第一个位置的情况
	{
		new_node = makeEmpty();
		new_node->data = x;
		new_node->next = head->next;
		head->next = new_node;
	}
	else  // 插入到其他位置
	{
		int i = 0;
		while ((++i) != pos && head->next != NULL)  // 如果pos大于链表长度,则自动改为尾插
		{
			head = head->next;
		}

		new_node = makeEmpty();
		new_node->data = x;
		new_node->next = head->next;
		head->next = new_node;
	}
}


// 4.2尾插
void backInsert(elemType x, LinkedList head)
{
	LinkedList p = head;  // 从头指针开始往后遍历(链表可能为空,此时没有第一个结点)

	LinkedList new_node = makeEmpty();  // 创建新结点
	new_node->data = x;

	while (p->next != NULL)  // 遍历到链表尾部进行插入
	{
		p = p->next;
	}
	p->next = new_node;
}


// 5.删除位置pos的结点
LinkedList deleteNode(int pos, LinkedList head)
{
	if (pos < 1)
	{
		printf("位置输入错误!\n");
		return NULL;
	}

	if (pos == 1)  // 删除第一个结点
	{
		LinkedList p = head->next;  // 拿到第一个结点
		if (p != NULL)
		{
			head->next = p->next;
			free(p);
			return head;
		}
		else
		{
			return NULL;
		}
		
	}
	else  // 删除其余结点
	{
		LinkedList p = find_nth(pos - 1, head);  // 找到要删除结点的前一个结点

		if (p == NULL || p->next == NULL)
		{
			printf("第%d个结点不存在!\n", pos);
			return NULL;
		}
		else
		{
			LinkedList temp = p->next;
			p->next = p->next->next;
			free(temp);
			printf("删除第%d个结点成功!\n", pos);
			return head;
		}
	}
}


// 6.返回链表的长度
int length(LinkedList head)
{
	LinkedList p = head->next;
	int count = 0;
	while (p)
	{
		p = p->next;
		count++;
	}
	return count;
}


// 7.输出链表
void print(LinkedList head)
{
	if (head->next == NULL)  // 链表为空
	{
		printf("链表为空!\n\n");
		return;
	}

	printf("打印链表:");
	
	LinkedList p = head;
	while (p->next != NULL)
	{
		p = p->next;
		printf("%d ", p->data);
	}
	printf("\n\n");
}

4.对链表进行测试操作

分布展示测试效果

    // 初始化链表
	LinkedList head = makeEmpty();

	// 4.2尾插
	backInsert(101, head);
	backInsert(102, head);
	backInsert(103, head);

    // 7.输出链表
	print(head);

    // 6.返回链表的长度
	printf("链表长度为:%d\n", length(head));

	system("pause");

    // 4.1在位置pos插入值为x的新结点
	insert(104, 1, head);
	insert(105, 3, head);
	insert(106, 1, head);

 

    // 5.删除位置pos的结点
	deleteNode(2, head);

    // 2.返回第n个元素结点
	LinkedList temp = find_nth(4, head);  // test1
	if (temp != NULL)
	{
		printf("第4个结点的数据为:%d\n", temp->data);
	}
	else
	{
		printf("未找到第4个结点!\n");
	}

	temp = find_nth(8, head);  // test2
	if (temp != NULL)
	{
		printf("第8个结点的数据为:%d\n", temp->data);
	}
	else
	{
		printf("未找到第8个结点!\n");
	}

    // 3.找到值为x的元素第一次出现的位置
	int pos = find(103, head);  // test1
	if (pos != NULL)
	{
		printf("第一次出现值为103的结点位置为:%d\n", pos);
	}
	else
	{
		printf("未找到值为103的结点!\n");
	}

	pos = find(108, head);  // test2
	if (pos != NULL)
	{
		printf("第一次出现值为108的结点位置为:%d\n", pos);
	}
	else
	{
		printf("未找到值为108的结点!\n");
	}

测试代码总览

// 测试代码
int main()
{
	// 初始化链表
	LinkedList head = makeEmpty();

	// 4.2尾插
	backInsert(101, head);
	backInsert(102, head);
	backInsert(103, head);

	// 4.1在位置pos插入值为x的新结点
	insert(104, 1, head);
	insert(105, 3, head);
	insert(106, 1, head);

	// 5.删除位置pos的结点
	deleteNode(2, head);


	// 7.输出链表
	print(head);

	// 2.返回第n个元素结点
	LinkedList temp = find_nth(4, head);  // test1
	if (temp != NULL)
	{
		printf("第4个结点的数据为:%d\n", temp->data);
	}
	else
	{
		printf("未找到第4个结点!\n");
	}

	temp = find_nth(8, head);  // test2
	if (temp != NULL)
	{
		printf("第8个结点的数据为:%d\n", temp->data);
	}
	else
	{
		printf("未找到第8个结点!\n");
	}

	// 3.找到值为x的元素第一次出现的位置
	int pos = find(103, head);  // test1
	if (pos != NULL)
	{
		printf("第一次出现值为103的结点位置为:%d\n", pos);
	}
	else
	{
		printf("未找到值为103的结点!\n");
	}

	pos = find(108, head);  // test2
	if (pos != NULL)
	{
		printf("第一次出现值为108的结点位置为:%d\n", pos);
	}
	else
	{
		printf("未找到值为108的结点!\n");
	}

	// 6.返回链表的长度
	printf("链表长度为:%d\n", length(head));

	system("pause");
	return 0;
}

合并链表:

5.操作链表的方法补充:

1.合并两个链表

// 8.1合并两个链表
LinkedList mergeLinkedList(LinkedList h1, LinkedList h2)  // 将h2接到h1后面
{
	LinkedList p = h1;

	while (p->next != NULL)  // 遍历到链表尾部进行插入
	{
		p = p->next;
	}
	p->next = h2->next;

	return h1;
}

 2.合并两个链表,并根据其数据大小进行排序

// 8.2合并两个链表,并根据其数据大小进行排序
LinkedList mergeLinkedListByAsc(LinkedList h1, LinkedList h2)  // 将h2接到h1后面
{
	// 先进行合并
	LinkedList p = h1;

	while (p->next != NULL)  // 遍历到链表尾部进行插入
	{
		p = p->next;
	}
	p->next = h2->next;

	// 再进行排序
	LinkedList pre_p;  // 双指针便于操作

	for (int i = 0; i < length(h1) - 1; i++)
	{
		// 指针重置
		pre_p = h1;
		p = h1->next;

		while (p != NULL && p->next != NULL)  // 遍历所有结点 (p != NULL为结点移动后,无后继元素,此时p后移为NULL)
		{
			if (p->next->data < p->data)
			{
				pre_p->next = p->next;
				p->next = pre_p->next->next;
				pre_p->next->next = p;

				pre_p = pre_p->next;  // 移动前指针
			}

			// 双指针后移
			pre_p = pre_p->next;
			p = p->next;
		}
	}

	return h1;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值