一、链表完整代码
【linkList.h】
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
//类型重定义,表示存放的数据类型
typedef int DataType;
//定义节点的结构体类型
typedef struct node
{
union
{
int len; //头节点数据域(表示链表长度)
DataType data; //普通节点的数据域
};
struct node* next; //节点的指针域
}linkList, *linkListPtr;
//创建链表(创建头节点)
linkListPtr create();
//判空
int empty(linkListPtr H);
//申请节点,封装数据
linkListPtr create_node(DataType e);
//头插
int head_add(linkListPtr H, DataType e);
//遍历
void show(linkListPtr H);
//尾插
int tail_add(linkListPtr H, DataType e);
//任意位置插入
int index_add(linkListPtr H, int index, DataType e);
//头删
int head_del(linkListPtr H);
//尾删
int tail_del(linkListPtr H);
//任意位置删除
int index_del(linkListPtr H, int index);
//按位置修改
int index_change(linkListPtr H, int index, DataType e);
//按值查找返回地址
linkListPtr node_addr(linkListPtr H, DataType e);
//反转
void node_rever(linkListPtr H);
//销毁
void my_free(linkListPtr H);
#endif
【linkList.c】
#include "linkList.h"
//创建链表(创建头节点)
linkListPtr create()
{
//在堆区申请节点大小空间,将地址返回给主程序使用
linkListPtr H = (linkListPtr)malloc(sizeof(linkList));
if(NULL == H)
{
printf("创建失败!\n");
return NULL;
}
//申请成功,将节点的数据域置为0,指针域置为NULL
H->len=0;
H->next=NULL;
printf("创建成功!\n");
return H;
}
//判空
int empty(linkListPtr H)
{
//判断所接受的链表是否合法
if(NULL == H)
{
printf("判空失败!\n");
return -1;
}
return H->len==0;
//return H->next==NULL;
}
//申请节点,封装数据
linkListPtr create_node(DataType e)
{
//在堆区申请普通节点大小空间
linkListPtr p=(linkListPtr)malloc(sizeof(linkList));
if(NULL == p)
{
printf("申请节点失败!\n");
return NULL;
}
//存放数据
p->data=e;
p->next=NULL;
return p;
}
//头插
int head_add(linkListPtr H, DataType e)
{
//判断所接受的链表是否合法
if(NULL == H)
{
printf("插入失败!\n");
return 0;
}
//申请节点,封装数据
linkListPtr p = create_node(e);
//头插
p->next=H->next;
H->next=p;
//插入成功,链表长度自增
H->len++;
return 1;
}
//遍历
void show(linkListPtr H)
{
//判断所接受的链表是否合法
//判空
if(NULL == H || empty(H))
{
printf("遍历失败!\n");
return;
}
//定义一个指针指向头节点(不可以改变头节点指针,需要复制一个去操作))
linkListPtr p=H;
for(int i=0; i<H->len; i++)
{
p=p->next;
printf("%d ", p->data);
}
printf("\n");
}
//尾插
int tail_add(linkListPtr H, DataType e)
{
//判断所接受的链表是否合法
if(NULL == H)
{
printf("插入失败!\n");
return 0;
}
//申请节点,封装数据
linkListPtr p = create_node(e);
//定义一个指针指向最后一个节点
linkListPtr q=H;
while(q->next != NULL)
{
q = q->next;
}
//尾插
q->next=p;
//插入成功,链表长度自增
H->len++;
return 1;
}
//任意位置插入
int index_add(linkListPtr H, int index, DataType e)
{
//判断所接受的链表是否合法
//判断插入的位置是否合理
if(NULL == H || index<1 || index>H->len+1)
{
printf("插入失败!\n");
return 0;
}
linkListPtr p = create_node(e);
//定义一个指针,指向要插入位置的前一个节点
linkListPtr q = H;
for(int i=0; i<index-1; i++)
{
q = q->next;
}
//插入
p->next=q->next;
q->next=p;
//插入成功,链表长度自增
H->len++;
return 1;
}
//头删
int head_del(linkListPtr H)
{
//判断所接受的链表是否合法
//判空
if(NULL==H || empty(H))
{
printf("删除失败!\n");
return 0;
}
//定义一个指针指向普通节点的第一个节点
linkListPtr q = H->next;
//删除
H->next = q->next; //等价于 H->next = H->next->next
//释放空间
free(q);
q=NULL;
//删除成功,链表长度自减
H->len--;
return 1;
}
//尾删
int tail_del(linkListPtr H)
{
//判断所接受的链表是否合法
//判空
if(NULL==H || empty(H))
{
printf("删除失败!\n");
return 0;
}
//定义一个指针指向最后一个节点的前一个节点
linkListPtr q = H;
for(int i=0; i<H->len-1; i++)
{
q=q->next;
}
//删除
free(q->next);
q->next=NULL;
//删除成功,链表长度自减
H->len--;
return 1;
}
//任意位置删除
int index_del(linkListPtr H, int index)
{
//判断所接受的链表是否合法
//判空
//判断删除位置是否合理
if(NULL== H || empty(H) || index<1 || index>H->len)
{
printf("删除失败!\n");
return 0;
}
//定义一个指针指向删除节点的前一个节点
linkListPtr q = H;
for(int i=0; i<index-1; i++)
{
q=q->next;
}
//定义一个指针指向要删除的节点
linkListPtr p = q->next;
//删除
q->next=q->next->next;
free(p);
p=NULL;
//删除成功,链表长度自减
H->len--;
return 1;
}
//按位置修改
int index_change(linkListPtr H, int index, DataType e)
{
//判断所接受的链表是否合法
//判空
//判断修改的位置是否合理
if(NULL== H || empty(H) || index<1 || index>H->len)
{
printf("修改失败!\n");
return 0;
}
//定义一个指针指向要修改的节点
linkListPtr p = H;
for(int i=0; i<index; i++)
{
p=p->next;
}
//判断是否修改的值是否相等
if(p->data==e)
{
return 0;
}
//修改数据
p->data=e;
return 1;
}
//按值查找返回地址
linkListPtr node_addr(linkListPtr H, DataType e)
{
//判断所接受的链表是否合法
//判空
if(NULL== H || empty(H))
{
printf("查询失败!\n");
return NULL;
}
//定义一个指针指向要查询的值的节点
linkListPtr p = H;
//遍历
for(int i=0; i<H->len; i++)
{
p = p->next;
if(p->data == e)
{
return p;
}
}
printf("查无此数据!\n");
return NULL;
}
//反转
void node_rever(linkListPtr H)
{
//判断所接受的链表是否合法
//判空
if(NULL== H || H->len<=1)
{
printf("查询失败!\n");
return;
}
//定义一个指针指向头节点的后一个节点
linkListPtr H2 = H->next;
//头指针的next置空
H->next = NULL;
while(H2 != NULL)
{
//标记要插入的节点
linkListPtr p = H2;
H2 = H2->next;
//头插
p->next=H->next;
H->next=p;
}
}
//销毁
void my_free(linkListPtr H)
{
//判断所接受的链表是否合法
if(NULL == H)
{
return;
}
while(H->next != NULL)
{
//头删
head_del(H);
}
//释放头节点
free(H);
H=NULL;
printf("销毁成功!\n");
}
【main.c】
#include "linkList.h"
int main()
{
//创建
linkListPtr H = create();
//头插
head_add(H, 10);
head_add(H, 20);
head_add(H, 30);
head_add(H, 40);
head_add(H, 50);
//遍历
show(H);
//尾插
tail_add(H, 11);
tail_add(H, 22);
tail_add(H, 33);
tail_add(H, 44);
tail_add(H, 55);
//遍历
show(H);
//任意位置插入
index_add(H, 3, 888);
//遍历
show(H);
//头删
head_del(H);
show(H);
head_del(H);
show(H);
//尾删
tail_del(H);
show(H);
tail_del(H);
show(H);
//任意位置删除
index_del(H, 3);
show(H);
//按位置修改
index_change(H, 3, 99);
show(H);
//按值查找返回地址
linkListPtr p = node_addr(H, 99);
p->data=666;
show(H);
//反转
node_rever(H);
show(H);
//销毁
my_free(H);
H=NULL;
return 0;
}