其他分享
首页 > 其他分享> > 线性表带头节点的链式存储和实现(C语言)【线性表】(5)

线性表带头节点的链式存储和实现(C语言)【线性表】(5)

作者:互联网

LinkList.h

#pragma 

/*------------------------------------------------------------
// 链表结构的定义
------------------------------------------------------------*/

typedef int ElemType;


typedef struct _Node
{
	ElemType data;				// 元素数据
	struct _Node* next;			// 链表中结点元素的指针
}Node, * NodePtr;

/*------------------------------------------------------------
// 链表的基本操作
------------------------------------------------------------*/

void InitList(NodePtr head);//单链表初始化
void DestroyList(NodePtr head, ElemType * data);//销毁
bool IsListEmpty(NodePtr head);//判空
int  ListLength(NodePtr head);//求链表长度
bool GetElem(NodePtr head, int pos,ElemType* data); //得到链表的第pos个元素
int LocateElem(NodePtr head, ElemType data);//得到链表指定元素的位置
Node* GetPosPrior(NodePtr head, int pos);//获得pos位置节点的前驱节点
Node* GetPosNext(NodePtr head, int pos);//获得pos位置节点的后继节点
void Show(NodePtr head); //打印单链表
bool ListInsert(NodePtr head, int pos, ElemType data);//在指定位置插入元素
void ListInsertHead(NodePtr head, ElemType data);//在链表的头部插入元素
void ListInsertTail(NodePtr head, ElemType data);//在链表的尾部插入元素
bool ListDeletePos(NodePtr head, int pos, ElemType* data);//删除指定位置的元素
void ListDeleteHead(NodePtr head, ElemType* data);//删除单链表的第一个元素
void ListDeleteTail(NodePtr head, ElemType* data);//删除单链表的最后一个元素
void ListDeleteData(NodePtr head, ElemType data);//删除与data相等数据的元素

LinkLlist.cpp

#include "LinkList.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <assert.h>

#define		ERROR_JUDGEMENT 	assert(NULL != head);\
if (NULL == head)\
{\
	printf("%s %d error\n", __FUNCTION__, __LINE__);\
	exit(-1);\
}

/*------------------------------------------------------------
操作目的:	初始化单链表
初始条件:	单链表不存在
操作结果:	创建一个空的单链表
函数参数:
		NodePtr head	待初始化单链表的头节点
返回值:
		void  无返回值
------------------------------------------------------------*/
void InitList(NodePtr head)
{
	ERROR_JUDGEMENT
	head->next = NULL;	
	head->data = 0;
}

/*------------------------------------------------------------
操作目的:	销毁单链表
初始条件:	单链表head已存在
操作结果:	单链表不存在
函数参数:
		NodePtr head	待销毁的单链表头结点
返回值:
		void 无
------------------------------------------------------------*/
void DestroyList(NodePtr head, ElemType* data)
{
	ERROR_JUDGEMENT
	while (head->next)
		ListDeleteHead(head,data);
}

/*------------------------------------------------------------
操作目的:	判断单链表是否为空
初始条件:	线性表head已存在
操作结果:	若单链表head为空表,则返回true,否则返回false
函数参数:
		NodePtr head	待判断的单链表
返回值:
		bool	返回  true 表示单链表为空				返回  false 表示单链表不为空
------------------------------------------------------------*/
bool IsListEmpty(NodePtr head)
{
	ERROR_JUDGEMENT
	return head->next == NULL ? true : false;
}

/*------------------------------------------------------------
操作目的:	得到单链表的长度
初始条件:	单链表head已存在
操作结果:	返回L中数据元素的个数
函数参数:
		NodePtr head	单链表的head头节点
返回值:
		int		单链表数据元素的个数
------------------------------------------------------------*/
int  ListLength(NodePtr head)
{
	ERROR_JUDGEMENT
	return head->data;
}

/*------------------------------------------------------------
操作目的:	得到单链表的pos位置元素
初始条件:	单链表L已存在,1<=i<=ListLength(head)
操作结果:	返回查找到的元素
函数参数:
		NodePtr head	单链表的head头节点
		int pos			数据元素的位置
		ElemType *data	存储查找到的元素数据
返回值:
		bool 查找到返回为true   没有找到返回为false
------------------------------------------------------------*/
bool GetElem(NodePtr head, int pos,ElemType *data)
{
	ERROR_JUDGEMENT
	Node* tmp = head->next;
	int j = 1;
	while (tmp && j < pos)
	{
		tmp = tmp->next;
		j++;
	}
	if (!tmp || j > pos)
		return false;
	else
	{
		*data = tmp->data;
		return true;
	}
}

/*------------------------------------------------------------
操作目的:	得到单链表指定元素的位置
初始条件:	单链表head已存在
操作结果:	返回单链表中查找到的和指定 data 相等的元素的下标
			若这样的元素不存在则返回0。
函数参数:
		NodePtr head	线性表head
		ElemType data	查找的元素
返回值:
		int   返回元素的位置  如果元素不存在则返回 0 
------------------------------------------------------------*/
int LocateElem(NodePtr head, ElemType data)
{
	ERROR_JUDGEMENT
	Node* tmp = head -> next;
	unsigned count = 0;
	while (tmp)
	{
		count++;
		if (data == tmp->data)
			return count;
		else
		{
			tmp = tmp->next;
		}
	}
	return 0;
}

/*------------------------------------------------------------
操作目的:	返回单链表中pos位置的前驱节点
初始条件:	单链表head已存在
操作结果:	返回单链表中pos位置的前驱节点的地址
函数参数:
		NodePtr head		线性表head
		int pos		   链表位置
返回值:
		Node* 返回前驱节点的指针
------------------------------------------------------------*/
Node* GetPosPrior(NodePtr head, int pos)
{
	ERROR_JUDGEMENT
	if (pos<1 || pos>head->data)
	{
		printf("pos error");
		exit(0);
	}
	Node* tmp =head;
	while (tmp && pos > 1)
	{
		tmp = tmp->next;
		pos--;
	}
	return tmp;
}

/*------------------------------------------------------------
操作目的:	返回单链表中pos位置的后继节点
初始条件:	单链表head已存在
操作结果:	返回单链表中pos位置的后继节点的地址
函数参数:
		NodePtr head		线性表head
		int pos				链表位置
返回值:
		返回pos位置的后继节点
------------------------------------------------------------*/

Node* GetPosNext(NodePtr head, int pos)
{
	ERROR_JUDGEMENT
	if (pos<1 || pos>head->data)
	{
		printf("pos error");
		exit(0);
	}
	Node* tmp = head;
	while (tmp && pos > 0)
	{
		tmp = tmp->next;
		pos--;
	}
	return tmp->next;
}
/*------------------------------------------------------------
操作目的:	打印单链表
初始条件:	单链表head已存在
操作结果:	依次打印链表中所有元素的数据域
函数参数:
		NodePtr head		线性表head
返回值:
		void
------------------------------------------------------------*/
void Show(NodePtr head)
{
	ERROR_JUDGEMENT
	Node* tmp = head->next;
	while (tmp)
	{
		printf("%d\t", tmp->data);
		tmp = tmp->next;
	}
	printf("\n");

}


/*------------------------------------------------------------
操作目的:	在单链表的指定位置插入结点,插入位置i表示在第i个
			元素之前插入
初始条件:	线性表head已存在,0<=i<=ListLength(head)
操作结果:	在head中第pos个位置插入新的数据元素data,head的长度加1
函数参数:
		NodePtr head	线性表head
		int pos		插入位置
		ElemType data	待插入的数据元素
返回值:
		void
------------------------------------------------------------*/
bool ListInsert(NodePtr head, int pos, ElemType data)
{
	ERROR_JUDGEMENT
	if (pos<1 || pos>head->data + 1)
	{
		printf("pos error");
		exit(0);
	}
	NodePtr p = head;
	int j = 0;
	while (p && j < pos - 1)
	{
		p = p->next;
		++j;
	}
	if (p && j > pos - 1)
	{
		return false;
	}
	NodePtr tmp = (NodePtr)malloc(sizeof(Node));
	tmp->data = data;
	tmp->next = p->next;
	p->next = tmp;
	head->data++;
	return true;
}


/*------------------------------------------------------------
操作目的:	在单链表的头部插入元素
初始条件:	单链表L已存在
操作结果:	在单链表的头部插入元素,head的长度加1
函数参数:
		NodePtr head	线性表head
		ElemType data	待插入的数据元素
返回值:
		bool		操作是否成功
------------------------------------------------------------*/
void ListInsertHead(NodePtr head, ElemType data)
{

	ERROR_JUDGEMENT
	ListInsert(head, 1, data);
}


/*------------------------------------------------------------
操作目的:	在单链表的尾部位置插入节点
初始条件:	单链表head已存在
操作结果:	在L中尾部插入节点,head的长度加1
函数参数:
		NodePtr head	    线性表head
		ElemType data	待插入的数据元素
返回值:
		无
------------------------------------------------------------*/
void ListInsertTail(NodePtr head, ElemType data)
{

	ERROR_JUDGEMENT
	ListInsert(head, head->data + 1, data);
}




/*------------------------------------------------------------
操作目的:	删除单链表的第i个结点
初始条件:	单链表存在
操作结果:	删除head的第i个数据元素
函数参数:
		NodePtr head	线性表head
		int pos   		删除位置

返回值:
		无返回值
------------------------------------------------------------*/
bool ListDeletePos(NodePtr head, int pos,ElemType * data)
{
	ERROR_JUDGEMENT
	if (pos<1 || pos>head->data)
		exit(0);
	NodePtr p = head, q;
	int j = 0;
	while (p->next && j < pos - 1)
	{
		p = p->next;
		++j;
	}
	if (!(p->next) || j > pos - 1)
		return false;

	q = p->next;
	p->next = q->next;
	*data = q->data;
	free(q);
	head->data--;
	return true;
}

/*------------------------------------------------------------
操作目的:	删除单链表的头节点
初始条件:	单链表head已存在且非空
操作结果:	删除head的头节点
函数参数:
		NodePtr head	线性表head
返回值:
		无返回值
------------------------------------------------------------*/
void ListDeleteHead(NodePtr head,ElemType *data)
{
	ERROR_JUDGEMENT
	ListDeletePos(head, 1, data);
}


/*------------------------------------------------------------
操作目的:	删除单链表的尾节点
初始条件:	单链表head已存在且非空
操作结果:	删除head的尾节点
函数参数:
		LinkList head	线性表head
返回值:
		无返回值
------------------------------------------------------------*/
void ListDeleteTail(NodePtr head, ElemType* data)
{
	ERROR_JUDGEMENT
	ListDeletePos(head, head->data,data);
}


/*------------------------------------------------------------
操作目的:	删除链表数据域为data的节点
初始条件:	线性表head已存在且非空
操作结果:	删除链表数据域为data的节点
函数参数:
		NodePtr head	线性表head
		ElemType data	被删除的数据元素值
返回值:
		无返回值
------------------------------------------------------------*/
void ListDeleteData(NodePtr head, ElemType data)   //删除与data相等数据的元素
{
	ERROR_JUDGEMENT
	Node* tmp = head->next;
	int count = 1;
	while (tmp)
	{
		if (tmp->data == data)
		{
			Node* PosPrior = GetPosPrior(head, count);
			Node* PosNode = PosPrior->next;
			PosPrior->next = PosNode->next;
			free(PosNode);
			return;
		}
		else
		{
			tmp = tmp->next;
			count++;
		}
	}
}

main.cpp

#include "LinkList.h"
#include <stdio.h>

int main()
{
	Node Head;
	ElemType data = 0;
	int pos = 1;

	InitList(&Head);//初始化

	for (int i = 1; i <= 10; i++)//调用头插法
	{
		ListInsertHead(&Head, i * 10);
	}
	Show(&Head);

	data = 999;
	pos = 4;
	printf("在单链表的第%d位置插入数据:%d\n",pos, data);
	ListInsert(&Head, pos, data);
	Show(&Head);

	data = 666;
	printf("在单链表的尾部插入数据%d:\n", data);
	ListInsertTail(&Head,data);
	Show(&Head);

	data = 119;
	printf("在单链表的头部插入数据%d:\n", data);
	ListInsertHead(&Head, data);
	Show(&Head);

	pos = 4;
	printf("删除单链表的%d位置元素:\n",pos);
	ListDeletePos(&Head, pos, &data);
	Show(&Head);

	printf("删除单链表头部位置的元素:\n");
	ListDeleteHead(&Head, &data);
	Show(&Head);

	printf("删除单链表头尾位置的元素:\n");
	ListDeleteTail(&Head, &data);
	Show(&Head);

	printf("获得单链表长度:\n");
	printf("%d\n", ListLength(&Head));

	pos = 3;
	printf("%d\n", GetElem(&Head, pos, &data));
	printf("获得单链表的第%d个位置的数据元素为%d\n",pos,data);

	data = 70;
	printf("数据元素%d所在的位置为%d\n", data, LocateElem(&Head, data));

	pos = 7;
	printf("获得第%d个数据元素的前驱结点数据:\n",pos);
	Node* PosPrior = GetPosPrior(&Head, pos);
	printf("pos %d prior node data : %d\n", pos, (*PosPrior).data);


	pos = 7;
	printf("获得第%d个数据元素的后继结点数据:\n", pos);
	PosPrior = GetPosNext(&Head, pos);
	printf("pos %d next node data : %d\n", pos, (*PosPrior).data);
	if (IsListEmpty(&Head))
		printf("单链表为空\n");
	else
		printf("单链表不为空\n");

	printf("销毁单链表\n");
	DestroyList(&Head, &data);
	if (!Head.next)
		printf("单链表销毁成功");
	return 0;
}

测试运行结果

单链表的基本使用测试结果

标签:tmp,head,单链,线性表,pos,C语言,NodePtr,链式,data
来源: https://blog.csdn.net/qq_43648751/article/details/107062200