单向链表操作总共分为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