单向链表操作

单向链表操作总共分为4个文件:

node.h

node.c

test.c

Makefile

现在将代码贴在下面仅供参考,直接可以运行:

node.h

#ifndef _NODE_H__
#define _NODE_H_

enum e_pos
{
	TAIL = -1,
	HEAD,
};
enum e_result
{
	ERROR = -1,
	OK,
	FALSE = 0,
	TRUE,
};

typedef int data_t ;
typedef struct node 
{
	data_t data;
	struct node * ptNext;
}NODE;

NODE * createLinkTableHead();
void destroyLinkTable(NODE *pHead);
int insertNodeToLinkTable(NODE *pHead, int offset, data_t newData);
int deleteNodeFromLinkTable (NODE *pHead, int offset, data_t *pData);
int updateDataToNode(NODE *pHead, data_t newData, data_t oldData);
int searchDataFromNode(NODE *pHead, data_t oldData);
void displayNodeData(NODE *pHead);
int isEmpty(const NODE *pHead);

#endif

node.c

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "node.h"
#define DEBUG

/* 创建链表头*/
NODE * createLinkTableHead()
{
	NODE *pHead = (NODE *)malloc(sizeof(NODE));
	if (NULL != pHead){
		pHead->data = 0;
		pHead->ptNext = NULL;
	}	
	return pHead;
}

/* 销毁整个链表(释放完全) */
void destroyLinkTable(NODE * pHead)
{
	/* pDel指向头节点 */
	NODE *pDel = pHead;	
	
	/* firstNode指向首节点 */
	NODE *pFirst = pDel->ptNext;    
	
	while (NULL != pFirst){
		/* 释放头节点 */
		free(pDel);	
		
		/* 移动 */
		pDel = pFirst;

		/* 移动 */
		pFirst = pFirst->ptNext;	
	}
	/* 释放最后一个节点 */
	free(pDel); 
	return;
}

/* 链表插入节点 */
int insertNodeToLinkTable(NODE * pHead, int offset, data_t newData)
{
	if (NULL == pHead){
		return ERROR;
	}
	
	/* 创建新结点pNew,并且初始化 */
	NODE *pNew = (NODE *)malloc(sizeof (NODE));
	if (NULL == pNew){
		return ERROR;
	}
	pNew->data = newData;
	pNew->ptNext = NULL;
	
	/* 头插(插到头节点后面) */
	if (HEAD == offset){
		/* 首节点连接到pNew后面 */
		pNew->ptNext = pHead->ptNext;
		
		/* 将pNew连接到头结点之后 */
		pHead->ptNext = pNew;
	}
	
	/* 尾插(找到尾节点,插到后面) */
	else if (TAIL == offset){
		NODE * pTail = pHead;
		
		/* 遍历,找到尾结点 */
		while (NULL != pTail->ptNext){
			pTail = pTail->ptNext;
		}
		
		/* 把新结点连接到尾结点之后,作为新的尾结点; */
		pTail->ptNext = pNew;
		pNew->ptNext = NULL;
	}
	
	/* 中间插入(在offset后面插入新的节点pNew) */
	else{
		NODE *q = pHead; /* 让q从头节点开始遍历 */

		/* i表示节点的位置从头节点开始 */
		int i=0;     
		while(i < offset && NULL != q){
			/* q往后移动 遍历找到offset的位置 */
			q = q->ptNext; 
			i++;		
		}

		/* 没有找到合适位置 */
		if(NULL == q){
			free(pNew);
			return ERROR;
		}
		/* 保护q后面的所有节点 */
		pNew->ptNext = q->ptNext;
		/* 把pNew连接到q后面 */
		q->ptNext = pNew; 
	}
	return 0;
}

/* displayNODE */
void displayNodeData(NODE * pHead)
{
	NODE * q = NULL;
	if (NULL == pHead){
		return ;
	}

	/* q指向首节点 */
	q = pHead->ptNext;
	while(NULL != q){
		printf("%d -> " , q->data);

		/* q移动 */
		q = q->ptNext;
	}
	printf("^\r\n");
}

/* 从链表删除某一个节点 */
int deleteNodeFromLinkTable (NODE * pHead, int offset, data_t * pData)
{
#ifdef DEBUG
	printf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
#endif

	NODE * pDel = NULL;
	if (NULL == pHead ||   NULL == pHead->ptNext){
		return ERROR;
	}

	/* 头删(删除首节点)*/
	if (HEAD == offset){
		/* pDel指向被删除的首结点 */
		pDel = pHead->ptNext;
		
		/* 保护pDel后的所有结点 */
		pHead->ptNext = pDel->ptNext;
		
		/* 保存pDel的数据域的值 */
		if (NULL != pData){
			*pData = pDel->data;
		}
		
		/* 释放pDel */
		free(pDel);
		pDel = NULL;
		
		return OK;
	}

	/* 尾删(删除尾结点) */
	else if (TAIL == offset)
	{
		
		 /* 定义q来保存被删除节点的前一个节点 */
		 NODE *q = pHead;

		 /* 找尾节点 */
		 pDel = pHead->ptNext;
		 while(NULL != pDel->ptNext){
			pDel = pDel->ptNext;
		 	q = q->ptNext; /* q保存前一个节点 */ 
		 }

		 /* 给尾节点前一节点的指针域赋值NULL */
		 q->ptNext = NULL;

		 /* 保存数据域的值 */
		 if(NULL != pData){
			 *pData = pDel->data;
		 }
		 /* 释放掉被删除的节点 */
		 free(pDel);
		 pDel = NULL;
		return OK;
	}

	/* 从中间删除某一个节点 */
	else 
	{
		/* 定义指针pDel指向被删除的节点,定义q指向pDel前一节点 */
		int i = 0;

		NODE *q = pHead; /* 定义q指向头节点 */

		pDel = q->ptNext;/* pDel指向首节点 */
	
		/* 找offset位置 */
		while(i<offset && NULL !=pDel){
			pDel = pDel->ptNext; /* 移动pDel */
			q = q -> ptNext;     /* 移动q */
			i++;
		}
		/* 保护被删除节点后面的节点 */
		q->ptNext = pDel->ptNext;

		/* 保存被删除节点的数据 */
		if(NULL != pData){
			*pData = pDel->data; /* 把被删除节点的数据拷贝出来 */
		}
		free(pDel); /* 被删除节点释放 */
		pDel = NULL;
		return OK;
	}	
	return OK;
}

/* 判断是否为空 */
int isEmpty(const NODE *pHead)
{
	if(NULL == pHead){
		return ERROR;
	}
	if(NULL == pHead->ptNext){
		return TRUE;
	}
	if(NULL != pHead->ptNext){
		return FALSE;
	}
	return ERROR;
}

/* 查找节点的数据 */
int searchDataFromNode(NODE * pHead, data_t oldData)
{
	/* 查找节点从首节点往后遍历 */
	NODE *pSerch = pHead->ptNext;
	int offset = 0;

	/* 从首节点开始往后找 */
	while(NULL != pSerch){
		/* 判断,如果数据相等,返回位置,否则输出找不到 */
		if(oldData == pSerch->data){
			return offset;
		}
		/* 往后移动查找链表 */
		pSerch = pSerch->ptNext;

		/* 移动一次,位置加1 */
		offset ++;
	}
	printf("找不到此数据\n");
	return ERROR;
}

/* 更新节点数据 */
int updateDataToNode(NODE * pHead, data_t newData, data_t oldData)
{
	NODE *pUpd = pHead;
	while(NULL != pUpd){
		if(oldData == pUpd->data){
			pUpd->data = newData;
			return OK;
		}
		pUpd = pUpd->ptNext;
	}
	return ERROR;
}

test.c

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

int main()
{
	NODE * pHead = NULL;
	data_t data ;
	
	/* 创建链表头结点 */
	pHead = createLinkTableHead();
	
	/* 插入数据 */
	insertNodeToLinkTable(pHead, HEAD, 1);
	insertNodeToLinkTable(pHead, HEAD, 2);
	insertNodeToLinkTable(pHead, TAIL, 3);
	insertNodeToLinkTable(pHead, TAIL, 4);
	insertNodeToLinkTable(pHead, HEAD, 5); /* 52134 */
	insertNodeToLinkTable(pHead, 3, 9);

	printf("insert value is:\n");
	displayNodeData(pHead);
	
	/* 删除首结点元素 */
	if ( OK == deleteNodeFromLinkTable ( pHead, HEAD, &data )){
		printf("删除头结点元素,被删除的元素是%d\n", data);
	}
	displayNodeData(pHead);

	/* 删除位置为3的元素 */
	if(OK == deleteNodeFromLinkTable ( pHead, 3, &data )){
		printf("删除位置为3的元素,被删除的元素是%d\n", data);
	}
	displayNodeData(pHead);


	/* 删除尾元素 */
	if(OK == deleteNodeFromLinkTable ( pHead, TAIL, &data )){
		printf("删除尾部元素,被删除的元素是%d\n", data);

	}
	displayNodeData(pHead);


	/* 判断是否为空 */
	if(1 == isEmpty(pHead)){
		printf("链表为空\n");
	}
	if(0 == isEmpty(pHead)){
		printf("链表不为空\n");
	}
	

	/* 查找数据 */
	int ret_serach = searchDataFromNode(pHead,9);
	if (ret_serach >=0){
		printf("查找到的元素的位置为%d\n",ret_serach);
	}

	/* 跟新值 */
	if (OK == updateDataToNode(pHead , 6 , 9)){
		printf("update success,将9更改成6\n");
	}
	displayNodeData(pHead);

	/* 销毁线性表 */
	destroyLinkTable(pHead);
	pHead = NULL;
	
	return 0;
}

 Makefile:

test:test.o node.o
	gcc test.o node.o -o test
test.o:test.c node.h
	gcc -c  -Wall -g -Werror test.c -o test.o
node.o:node.c node.h
	gcc -c  -Wall -g -Werror node.c  -o node.o
.PHONY:clean
clean:
	rm -rf test *.o

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

潘良荣

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

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

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

打赏作者

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

抵扣说明:

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

余额充值