欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

线性表之链表(单链表)

程序员文章站 2022-06-06 13:39:13
...

线性表:由n(n>=0)个相同类型数据元素组成,并且可以 在任意位置进行插入和删除数据元素操作的有限序列。

线性表之链表(单链表)

单链表:它是一种链式存储的线性表,用一组地址任意的存储单元存放线性表        的数据元素,称存储单元为一个节点。

线性表之链表(单链表)线性表之链表(单链表)

线性表之链表(单链表)


线性表之链表(单链表)

代码实现:

list.h

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

typedef int DataType;
typedef struct node
{
	DataType data;
	struct node* next;

}Node, *pNode, *pList;


pNode Create(DataType d);  //创建链表
void PushBack(pList p_list, DataType d);//尾插
void PrintList(pList p_list);//打印
void PrintListrecur(pList p_list); //递归倒叙打印链表
void PrintListBack(pList p_list);//倒序打印
pNode Find(pList p_list, DataType x); //查找
void DeleteNohead(pNode pos);//删除无头节点的非尾节点
void InsertNohead(pNode pos,DataType d);///插入无头结点的非头结点
pNode JosephList(pList p_list); //链表环化
pNode JosepListK(pList p_list, int k);
pNode Lnverse(pList p_list);//逆置链表
pNode MergeList(pList p_list1, pList p_list2);//合并两个链表
pNode QsortMergeList(pList p_list1, pList p_list2);//合并有序两个链表之后依然有序
pNode FindMidNode(pList p_list);//查找中间节点
pNode FindThelastK(pList p_list, int k);//查找倒数第K个节点


#endif //__LIST_H__
list.c
#include"List.h"


pNode Create(DataType d)//创建
{
	pNode p_list = (pNode)malloc(sizeof(Node));
	if (p_list == NULL)
	{
		return NULL;
	}
	p_list->data = d;
	p_list->next = NULL;
	return p_list;

}

void PushBack(pList p_list, DataType d)//尾插
{
	pNode p1 = p_list;
	pNode p2 = NULL;
	p2 = (pNode)malloc(sizeof(Node));
	if (p2 == NULL)
	{
		return;
	}
	while (p1->next != NULL)
	{
		p1 = p1->next;
	}
	p2->data = d;
	p1->next = p2;
	p2->next = NULL;
}

void PrintList(pList p_list)//打印
{
	assert(p_list);
	while (p_list->next != NULL)
	{
		printf("%d->", p_list->data);
		p_list = p_list->next;
	}

	printf("%d->NULL\n", p_list->data);
}

//一.从尾到头打印链表
void PrintListrecur(pList p_list) //递归倒叙打印链表
{
	if (p_list != NULL)
	{
		if (p_list->next != NULL)
		{
			PrintListrecur(p_list->next);
		}
		printf("%d->", p_list->data);     
	}
	
}

pNode l = NULL;
void PrintListBack(pList p_list)  //倒序打印
{
	pNode p;
	p = p_list;
	while (p != NULL)
	{
		while (p != l)
		{
			pNode q = NULL;
			q = p;

			if (q->next == l)
			{
				printf("%d->", p->data);
				break;
			}
			p = p->next;
		}
		l = p;
		if (l == p_list)
			break;
		p = p_list;
	}
	printf("\n");
}

//二.删除无头结点的非尾节点(不能遍历链表)
pNode Find(pList p_list, DataType x)  //查找
{
	pNode p, q;
	p = p_list;
	q = NULL;
	while (p->next->data != x&&p->next != NULL)
	{
		p = p->next;
		if (p->next == NULL)
		{
			printf("没有找到\n");
			return NULL;
		}
	}
	printf("找到了\n");
	return (p = p->next);
}

void DeleteNohead(pNode pos) //删除无头节点非尾节点
{
	assert(pos);
	pNode ptmp1 = NULL;
	pNode ptmp2 = NULL;
	ptmp1 = pos->next;
	ptmp2 = ptmp1->next;
	DataType tmp=pos->data;
	pos->data = ptmp1->data;
	ptmp1->data = tmp;
	pos->next = ptmp2;
	ptmp1->next = NULL;
	free(ptmp1);
}

//三.在无头单链表的一个非头节点前插入一个节点
void InsertNohead(pNode pos,DataType d) //插入无头结点的非头结点前
{
	assert(pos);
	pNode ptmp1 = NULL;
	pNode ptmp2 = NULL;
	ptmp2 = pos->next;
	ptmp1 = (pNode)malloc(sizeof(Node));
	if (ptmp1 == NULL)
		return;
	ptmp1->data = d;
	pos->next = ptmp1;
	ptmp1->next = ptmp2;
	DataType tmp = pos->data;
	pos->data = ptmp1->data;
	ptmp1->data = tmp;
}

//四.单链表实现约瑟夫环(JosephCircle)
pNode JosephList(pList p_list) //链表环化
{
	pNode p = p_list;
	while (p_list->next != NULL)
	{
		p_list = p_list->next;
	}
	p_list->next = p;
	return p;
}

pNode JosepListK(pList p_list, int k)
{
	int i = 0;
	for (i = 0; i < k - 1; i++)
	{
		p_list = p_list->next;
	}
	pNode p1 = p_list;
	pNode p2 = p_list->next;
	pNode p3 = p_list->next->next;
	p1->next = p3;
	free(p2);
	if (p1->next == p1)
		return p1;
	JosepListK(p3, k);
}

//五.链表逆置
pNode Lnverse(pList p_list)//逆置链表
{
	assert(p_list);
	pNode pHead = NULL;
	pNode p1 = p_list;
	pNode pt = NULL;
	while (p1 != NULL)
	{
		pNode p2 = p1->next;
		if (p2 == NULL)
			pHead = p1;
		p1->next = pt;
		pt = p1;
		p1 = p2;
	}
	return pHead;

}

//六.合并两个有序链表, 合并后依然有序
pNode MergeList(pList p_list1, pList p_list2)//合并两个链表
{
	assert(p_list1);
	assert(p_list2);

	pNode p = p_list1;
	while (p->next != NULL)
	{
		p = p->next;
	}
	p->next = p_list2;
	return p_list1;
}

pNode QsortMergeList(pList p_list1, pList p_list2)//合并有序两个链表之后依然有序
{
	pNode newhead = NULL;
	if ((p_list1 == NULL) && (p_list2 != NULL))
	{
		return p_list2;
	}
	if ((p_list1 != NULL) && (p_list2 == NULL))
	{
		return p_list1;
	}
	if ((p_list1->data) >= (p_list2->data))
	{
		newhead = p_list1;
		newhead->next = QsortMergeList(p_list1->next, p_list2);
	}
	else
	{
		newhead = p_list2;
		newhead->next = QsortMergeList(p_list1, p_list2->next);
	}
	return newhead;
}

//七.查找单链表的中间节点,要求只能遍历一次链表
pNode FindMidNode(pList p_list)//查找中间节点
{
	assert(p_list);
	pNode p1 = p_list;
	pNode p2 = p_list;
	while (p2->next->next != NULL)
	{
		p1 = p1->next;
		p2 = p2->next->next;
		if (p2->next == NULL)
		{
			return p1;
		}
	}
	return p1;
}

//八.查找单链表的倒数第k个节点,要求只能遍历一次链表
pNode FindThelastK(pList p_list, int k)//查找倒数第K个节点
{
	pNode p1 = p_list;
	pNode p2 = p_list;
	int i = 0;
	for (i = 0; i < k - 1; i++)
	{
		p2 = p2->next;
	}
	while (p2->next != NULL)
	{
		p2 = p2->next;
		p1 = p1->next;
	}
	return p1;
}
test.c 部分测试
#include"List.h"

void test1()
{
	pNode p = NULL;

	p=Create(5);
	PushBack(p, 4);
	PushBack(p, 3);
	PushBack(p, 2);
	PushBack(p, 1);
	PushBack(p, 0);
	PrintList(p);
	PrintListrecur(p);
	printf("\n");
	PrintListBack(p);
	pNode pos=Find(p, 2);
	DeleteNohead(pos);
	PrintList(p);
}
void test2()
{
	pNode p = NULL;

	p = Create(5);
	PushBack(p, 4);
	PushBack(p, 2);
	PushBack(p, 1);
	PushBack(p, 0);
	PrintList(p);
	pNode pos=Find(p, 2);
	InsertNohead(pos, 3);
	PrintList(p);
}

int main()
{
//	test1();
	test2();
	return 0;

}