数据结构(一)线性结构(2)链表

链表是线性表的另一种表示方法,其特点是每个元素包含数据域和指针域,指针域的存在使得链表元素之间在空间上不必连续(即地址不连续),并且链表元素节点可以用时分配,比顺序表要灵活,但如果节点数较多,耗费空间资源比顺序表要多

链表有单向链表、双向链表、十字链表、循环链表等,这里仅简单介绍单向链表,其它链表形式大同小异

其基本定义:

typedef struct LIST{
    int idata;
    struct LIST *ptNext;
}T_List, *PT_List;

idata是节点的数据域,ptNext为指针域,指向下一个节点

 

为链表提供一个头节点,会给链表(对头部节点的)操作带来极大的便利,下面会给出无头节点和有头节点两个版本的代码

 

 

链表主要操作有:

1、创建一个链表:PT_List createList(void)

在无头节点版本中,创建链表要知道第一个数据的值

在有头节点版本中,创建链表只需要创建一个头节点,不需要有实际的元素

2、从链表中查找指定元素节点:PT_List findInList(int iX, PT_List ptHead)

两版本查找元素过程是一致的,只需要判空然后按照节点指针域遍历节点的数据域即可

3、从链表中修改指定节点的数据域:PT_List alterInList(int iNew, int iPre, PT_List ptHead, int iFlag)

两版本的修改节点数据域过程一致,根据数据域找到指定节点进行修改即可

4、向链表插入元素节点:PT_List addToList(int iNew, int iPre, PT_List ptHead, int iFlag)

插入节点可以分为从链表头插入、从链表尾插入、从链表中某个节点后插入

对于无头节点版本,无论哪种插入,都需要判空,如果链表为空,则创建第一个节点,如果不为空,从链表头插入时,可以采用两种方法:①创建新节点,新节点的指针域指向原链表第二个节点,然后原链表第一个节点的指针域指向新节点,这样就把新节点插入到原链表的第一、第二节点之间,然后把新节点数据域与第一个节点数据域交换即可;②创建新节点,指针域指向链表第一个节点,保存新节点数据域后,修改链表头部指针,指向新节点,这要求子函数传入参数为二重指针

对于有头节点版本,从链表头插入时,只需要按照①的方法插入即可,数据域无需交换,因为头节点只起标志性作用,不作为真实数据节点

后面两种插入方法,有无头节点其过程都是一致的(除了无头节点情况需要判空以外)

从链表尾插入时,遍历找到尾节点(单链表查找依据是指针域为NULL),然后让尾节点指向新节点即可从某个节点后插入时,遍历找到特定节点(查找依据是数据域),然后用变量暂存特定节点的下一个节点,插入过程类似从链表头插入

5、从链表中删除指定节点PT_List deleteFromList(int iX, PT_List ptHead, int iFlag)

删除节点也可以分为删除头节点、尾节点、中间节点三种情况,方法类似插入节点

 

无头节点版本代码:

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

#ifdef DEBUG_LIST_VERSION_1



#define MENU_EXIT				0
#define MENU_FIND				1
#define MENU_ADD				2
#define MENU_ALTER				3
#define MENU_DELETE				4
#define MENU_PRINT				5


#define ADD_IN_HEAD			1
#define ADD_IN_TAIL			2
#define ADD_IN_MID			3
#define DELETE_ONE_VALUE	1		
#define DELETE_ALL_VALUE	2	
#define ALTER_ONE			1	
#define ALTER_ALL			2

typedef struct LIST{
	int idata;
	struct LIST *ptNext;
}T_List, *PT_List;


PT_List createList(void)
{
	int i, iNum;
	PT_List ptHead, ptPre, ptTmp;

	printf("Enter the num of nodes: ");
	scanf_s("%d", &iNum);
	if (iNum <= 0)
	{
		printf("Err: num <= 0\r\n");
		return NULL;
	}

	printf("Enter your data: ");
	ptHead = (PT_List)malloc(sizeof T_List);
	scanf_s("%d", &ptHead->idata);
	ptHead->ptNext = NULL;
	ptPre = ptHead;

	for (i = 1; i < iNum; i++)
	{		
		ptTmp = (PT_List)malloc(sizeof T_List);
		scanf_s("%d", &ptTmp->idata);
		ptTmp->ptNext = NULL;
		ptPre->ptNext = ptTmp;	
		ptPre = ptTmp;
	}

	return ptHead;
}

void printList(PT_List ptHead)
{
	PT_List ptTmp = ptHead;
	
	printf("\r\n");
	if(!ptTmp)
		printf("List is empty\r\n");
	while (ptTmp)
	{
		printf("%d ", ptTmp->idata);
		ptTmp = ptTmp->ptNext;
	}
	printf("\r\n\r\n");
}

PT_List findTheListTail(PT_List ptHead)
{
	PT_List	ptTmp = ptHead;

	while (ptTmp->ptNext)
		ptTmp = ptTmp->ptNext;

	return ptTmp;
}

PT_List findBeforeOne(int iX, PT_List ptHead)
{
	PT_List ptTmp = ptHead, ptPre = NULL;
	int i = 1;


	while (ptTmp->idata != iX && ptTmp->ptNext)
	{
		ptPre = ptTmp;
		ptTmp = ptTmp->ptNext;
		i++;
	}
	if (ptTmp->idata != iX)
	{
		printf("Can't Find the node %d\r\n", iX);
		return NULL;
	}
	printf("Find the node in %d\r\n", --i);

	return ptPre;
}

PT_List findInList(int iX, PT_List ptHead)
{
	PT_List ptTmp = ptHead;
	int i = 1;

	if (!ptHead)
	{
		printf("List is empty\r\n");
		return NULL;
	}
	while (ptTmp->idata != iX && ptTmp->ptNext)
	{
		ptTmp = ptTmp->ptNext;
		i++;
	}
	if (ptTmp->idata != iX)
	{
		printf("Can't Find the node %d\r\n", iX);
		return NULL;
	}

	return ptTmp;
}

PT_List addToList(int iNew, int iPre, PT_List *pptHead, int iFlag)
{
	PT_List ptTmp = NULL, ptNew;
	int iTmp;

	if (iFlag != ADD_IN_HEAD && iFlag != ADD_IN_TAIL && iFlag != ADD_IN_MID)
	{
		printf("Err in iFlag\r\n");
		return NULL;
	}

	ptNew = (PT_List)malloc(sizeof T_List);
	if (!ptNew)
	{
		printf("Err in memory\r\n");
		return NULL;
	}
	if (!*pptHead)
	{
		*pptHead = ptNew;
		(*pptHead)->idata = iNew;
		(*pptHead)->ptNext = NULL;
		return *pptHead;
	}


	if (iFlag == ADD_IN_HEAD)
	{
		ptNew->ptNext =( *pptHead)->ptNext;
		(*pptHead)->ptNext = ptNew;
		iTmp = iNew;
		ptNew->idata = (*pptHead)->idata;
		(*pptHead)->idata = iTmp;
	}
	else if (iFlag == ADD_IN_TAIL)
	{
		ptTmp = findTheListTail(*pptHead);
		ptTmp->ptNext = ptNew;
		ptNew->ptNext = NULL;
		ptNew->idata = iNew;
	}
	else if (iFlag == ADD_IN_MID)
	{
		ptTmp = findInList(iPre, (*pptHead));
		if (!ptTmp)
		{
			printf("Err in the location\r\n");
			free(ptNew);
			return NULL;
		}
		ptNew->ptNext = ptTmp->ptNext;
		ptTmp->ptNext = ptNew;
		ptNew->idata = iNew;
	}

	return *pptHead;
}

PT_List alterInList(int iNew, int iPre, PT_List ptHead, int iFlag)
{
	PT_List ptTmp;
	
	if (iFlag != ALTER_ONE && iFlag != ALTER_ALL)
	{
		printf("Err in iFlag\r\n");
		return NULL;
	}

	ptTmp = findInList(iPre, ptHead);
	if (!ptTmp)
		return NULL;
	do
	{
		ptTmp->idata = iNew;
		if (iFlag == ALTER_ONE)
			break;
		ptTmp = findInList(iPre, ptHead);
	} while (ptTmp);


	return ptHead;
}

PT_List deleteFromList(int iX, PT_List *pptHead, int iFlag)
{
	PT_List ptPre, ptTmp = NULL;

	if(iFlag != DELETE_ONE_VALUE && iFlag != DELETE_ALL_VALUE)
	{
		printf("Err in iFlag\r\n");
		return NULL;
	}

	if (!(*pptHead)->ptNext)
	{
		ptTmp = *pptHead;
		*pptHead = NULL;
		free(ptTmp);
		return NULL;
	}

	while ((*pptHead)->idata == iX)
	{
		ptTmp = (*pptHead)->ptNext;
		(*pptHead)->idata = ptTmp->idata;
		(*pptHead)->ptNext = ptTmp->ptNext;
		free(ptTmp);
		if (iFlag == DELETE_ONE_VALUE)
			return *pptHead;
	}
	ptPre = findBeforeOne(iX, *pptHead);
	if (!ptPre)
	{
		printf("Err in the element\r\n");
		return NULL;
	}
	while (ptPre)
	{
		ptTmp = ptPre->ptNext;
		ptPre->ptNext = ptTmp->ptNext;
		free(ptTmp);
		if (iFlag == DELETE_ONE_VALUE)
			break;
		ptPre = findBeforeOne(iX, *pptHead);
	}

	return *pptHead;
}

int menu(PT_List *pptHead)
{
	int iNum, iEle, iTmp = 0;

	printf(	"Enter\r\n"
			"0 to exit\r\n"
			"1 to find\r\n"
			"2 to add\r\n"
			"3 to alter\r\n"
			"4 to delete\r\n"
			"5 to print\r\n");

	scanf_s("%d", &iNum);
	switch (iNum)
	{
		case MENU_EXIT:
			return -1;
		case MENU_FIND:
			printf("Enter the element: ");
			scanf_s("%d", &iEle);
			findInList(iEle, *pptHead);
			break;
		case MENU_ADD:
			printf( "Enter\r\n"
					"1 to add in head\r\n"
					"2 to add in tail\r\n"
					"3 to add in mid\r\n");
			scanf_s("%d", &iNum);
			if (iNum == ADD_IN_MID)
			{
				printf("Enter the num before the one to be altered: ");
				scanf_s("%d", &iTmp);
			}
			printf("Enter the element: ");
			scanf_s("%d", &iEle);
			addToList(iEle, iTmp, pptHead, iNum);
			break;
		case MENU_ALTER:
			printf("Enter\r\n"
				"1 to alter one\r\n"
				"2 to alter all\r\n");
			scanf_s("%d", &iNum);
			printf("Enter the Pre element: ");
			scanf_s("%d", &iTmp);
			printf("Enter the new element: ");
			scanf_s("%d", &iEle);
			alterInList(iEle, iTmp, *pptHead, iNum);
			break;
		case MENU_DELETE:
			printf("Enter\r\n"
				"1 to delete in one\r\n"
				"2 to delete in all\r\n");
			scanf_s("%d", &iNum);
			printf("Enter the element: ");
			scanf_s("%d", &iEle);
			deleteFromList(iEle, pptHead, iNum);
			break; 
		case MENU_PRINT:
			printList(*pptHead);
			break;
	}

	return 0;
}

int main(void)
{
	PT_List ptHead;
	
	ptHead = createList();
	if (!ptHead)
		return -1;

	
	while (menu(&ptHead) >= 0);

	return 0;
}

#endif

 

 

 

 

 

有头节点版本代码:

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

#ifdef DEBUG_LIST_VERSION_2

#define MENU_EXIT	0
#define MENU_FIND	1
#define MENU_ADD	2
#define MENU_ALTER	3
#define MENU_DELETE	4
#define MENU_PRINT	5

#define ADD_IN_HEAD	1
#define ADD_IN_TAIL	2
#define ADD_IN_MID	3

#define ALTER_ONE	1
#define ALTER_ALL	2

#define DELETE_ONE	1
#define DELETE_ALL	2

typedef struct LIST {
	int idata;
	struct LIST *ptNext;
}T_List, *PT_List;

PT_List createList(void)
{
	PT_List ptPre, ptNew, ptHead;
	int iNum;

	printf("Enter the num of nodes: ");
	scanf_s("%d", &iNum);
	if (iNum < 0)
	{
		printf("Err in the num of nodes\r\n");
		return NULL;
	}
	ptHead = (PT_List)malloc(sizeof T_List);
	ptHead->ptNext = NULL;
	ptPre = ptHead;
	printf("Enter your data: ");
	while (iNum-- > 0)
	{
		ptNew = (PT_List)malloc(sizeof T_List);
		scanf_s("%d", &ptNew->idata);
		ptNew->ptNext = NULL;
		ptPre->ptNext = ptNew;
		ptPre = ptNew;
	}

	return ptHead;
}

void printList(PT_List ptHead)
{
	PT_List ptTmp = ptHead->ptNext;

	printf("\r\n");
	if (!ptTmp)
		printf("List is empty\r\n");
	while (ptTmp)
	{
		printf("%d ", ptTmp->idata);
		ptTmp = ptTmp->ptNext;
	}
	printf("\r\n\r\n");
}

int isEmpty(PT_List ptHead)
{
	return ptHead->ptNext == NULL ? 1: 0;
}

PT_List findListTail(PT_List ptHead)
{
	PT_List ptTmp = ptHead->ptNext;

	if (isEmpty(ptHead))
	{
		printf("List is empty\r\n");
		return NULL;
	}

	while (ptTmp->ptNext)
		ptTmp = ptTmp->ptNext;

	return ptTmp;
}

PT_List findInList(int iX, PT_List ptHead)
{
	PT_List ptTmp = ptHead->ptNext;
	int i = 1;

	if (isEmpty(ptHead))
	{
		printf("List is empty\r\n");
		return NULL;
	}
	while (ptTmp->idata != iX && !isEmpty(ptTmp))
	{
		i++;
		ptTmp = ptTmp->ptNext;
	}
	if (ptTmp->idata != iX)
	{
		printf("Can't find the %d\r\n", iX);
		return NULL;
	}
	printf("Find the node %d in %d\r\n", iX, i);

	return ptTmp;
}

PT_List addToList(int iNew, int iPre, PT_List ptHead, int iFlag)
{
	PT_List ptNew, ptTmp, ptPre;

	if (iFlag != ADD_IN_HEAD && iFlag != ADD_IN_TAIL && iFlag != ADD_IN_MID)
	{
		printf("Err in iFlag\r\n");
		return NULL;
	}
	ptNew = (PT_List)malloc(sizeof T_List);
	ptNew->idata = iNew;
	ptNew->ptNext = NULL;
	switch (iFlag)
	{
		case ADD_IN_HEAD:
			ptTmp = ptHead->ptNext;
			ptHead->ptNext = ptNew;
			ptNew->ptNext = ptTmp;
			break;
		case ADD_IN_TAIL:
			ptPre = findListTail(ptHead);
			ptPre->ptNext = ptNew;
			break;
		case ADD_IN_MID:
			ptPre = findInList(iPre, ptHead);
			ptTmp = ptPre->ptNext;
			ptNew->ptNext = ptTmp;
			ptPre->ptNext = ptNew;
			break;
	}

	return ptHead;
}


PT_List alterInList(int iNew, int iOld, PT_List ptHead, int iFlag)
{
	PT_List ptTmp;

	if (iFlag != ALTER_ONE && iFlag != ALTER_ALL)
	{
		printf("Err in iFlag\r\n");
		return NULL;
	}

	ptTmp = findInList(iOld, ptHead);
	if (!ptTmp)	
		return NULL;
	
	while (ptTmp)
	{
		ptTmp->idata = iNew;
		if (iFlag == ALTER_ONE)
			break;
		ptTmp = findInList(iOld, ptHead);
	}

	return ptHead;
}

PT_List findBeforeOne(int iEle, PT_List ptHead)
{
	PT_List ptTmp = ptHead->ptNext, ptPre = ptHead;

	if (isEmpty(ptHead))
	{
		printf("List is empty\r\n");
		return NULL;
	}
	
	while (ptTmp->idata != iEle && ptTmp->ptNext)
	{
		ptPre = ptTmp;
		ptTmp = ptTmp->ptNext;
	}

	if (ptTmp->idata != iEle)
	{
		printf("Can't find the element\r\n");
		return NULL;
	}

	return ptPre;
}

PT_List deleteFromList(int iEle, PT_List ptHead, int iFlag)
{
	PT_List ptPre, ptTmp;
	if (iFlag != DELETE_ONE && iFlag != DELETE_ALL)
	{
		printf("Err in iFlag\r\n");
		return NULL;
	}

	ptPre = findBeforeOne(iEle, ptHead);
	while (ptPre)
	{
		ptTmp = ptPre->ptNext;
		if (!ptTmp->ptNext)
			ptPre->ptNext = NULL;
		else
			ptPre->ptNext = ptTmp->ptNext;
		free(ptTmp);
		if (iFlag == DELETE_ONE)
			break;
		ptPre = findBeforeOne(iEle, ptHead);
	}

	return ptHead;
}

int menu(PT_List ptHead)
{
	int iNum, iEle, iLoc = 0;

	printf("Enter\r\n"
		"0 to exit\r\n"
		"1 to find\r\n"
		"2 to add\r\n"
		"3 to alter\r\n"
		"4 to delete\r\n"
		"5 to print\r\n");

	scanf_s("%d", &iNum);
	switch (iNum)
	{
		case MENU_EXIT:
			return -1;
		case MENU_FIND:
			printf("Enter the element to be found: ");
			scanf_s("%d", &iEle);
			findInList(iEle, ptHead);
			break;
		case MENU_ADD:
			printf("Enter\r\n"
				"1 to add in head\r\n"
				"2 to add in tail\r\n"
				"3 to add in mid\r\n");
			scanf_s("%d", &iNum);
			printf("Enter the element to be added: ");
			scanf_s("%d", &iEle);
			if (iNum == ADD_IN_MID)
			{
				printf("Enter the element before the one to be added: ");
				scanf_s("%d", &iLoc);
			}
			addToList(iEle, iLoc, ptHead, iNum);
			break;
		case MENU_ALTER:
			printf("Enter\r\n"
				"1 to alter one\r\n"
				"2 to alter all\r\n");
			scanf_s("%d", &iNum);
			printf("Enter the Pre element: ");
			scanf_s("%d", &iLoc);
			printf("Enter the new element: ");
			scanf_s("%d", &iEle);
			alterInList(iEle, iLoc, ptHead, iNum);
			break;
		case MENU_DELETE:
			printf("Enter\r\n"
				"1 to delete in one\r\n"
				"2 to delete in all\r\n");
			scanf_s("%d", &iNum);
			printf("Enter the element: ");
			scanf_s("%d", &iEle);
			deleteFromList(iEle, ptHead, iNum);
			break;
		case MENU_PRINT:
			printList(ptHead);
			break;
	}

	return 0;
}

int main(void)
{
	PT_List ptHead;

	ptHead = createList();
	if (!ptHead)
		return -1;

	while (menu(ptHead) >= 0);

	return 0;
}

#endif

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值