线性表带头节点的链式存储和实现(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