LinkList.h
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0typedef int ElemType;//假定线性表的元素类型为整型
//定义单链表的节点
typedef struct node
{
int data;
struct node *pNext;
}LinkListNode;
///创建带有头节点的链表Init
///函数的返回值是头节点,没有参数
LinkListNode* InitLinkList(void);
///求长度:求顺序表中的元素的个数
///函数的返回值是顺序表的长度,参数pHead:是单链表的头节点
int GetSizeLinkList(LinkListNode* pHead);
///取元素:取给定位置的元素值
///返回值:第i个元素的地址,pHead:头指针,i 待查节点的序号
LinkListNode* GetLinkListNode(LinkListNode* pHead, int pos);
///查元素:查找给定元素值的位置
///返回值:节点的地址,找不到就返回NULL
///pHead:单链表的头指针,objData:是需要匹配的元素值
LinkListNode* LocateLinkList(LinkListNode* pHead, int objData);
///插入元素:在指定的位置插入给定的值
///尾插法建立单链表(将逻辑上的顺序表放入单链表的物理结构当中)
///返回值:链表的头指针,arr:传入的顺序表,length:顺序表的长度
LinkListNode* Create_Rear_LkList(ElemType arr[], int length);
///头插法建立单链表
///返回值:链表的头指针,arr:传入的顺序表,length:顺序表的长度
LinkListNode* Create_Front1_LkList(ElemType arr[], int length);
///头插法2
///返回值:链表的头指针,arr:传入的顺序表,length:顺序表的长度
LinkListNode* Create_Front2_LkList(ElemType arr[], int length);
///头插法建立
///返回值:链表的头指针,arr:传入的顺序表,length:顺序表的长度
LinkListNode* Create_Front3_LkList(ElemType arr[], int length);
///插入元素:在指定的位置插入给定的值
//ptr:带插入的元素位置,将在ptr的后继结点中插入,x:插入的值
void Insert_After_LkList(LinkListNode* ptr, ElemType x);
///指定位置之前插入
///pHead:链表的头指针,ptr:带插入的元素位置,x:插入的值
void Insert_Before_LkList(LinkListNode* pHead, LinkListNode* ptr, ElemType x);
///删除节点:Ptr是需要删除的节点,将删除ptr的后续节点
///返回值是带删除的节点位置
LinkListNode* Delete_After_LkList(LinkListNode* ptr);
///删除第i个节点
///返回值是带删除的节点位置,pHead:头节点,i是第i个元素
LinkListNode* Delete_i_LkList(LinkListNode* pHead, int i);
///遍历
void ShowLkList(LinkListNode* pHead);
LinkList.c
#include "LinkList.h"
/*
1) 初始化:给线性表中的相关参数赋值
2) 求长度:求线性表中的元素的个数
3) 取元素:取给定位置的元素值
4) 查元素:查找给定元素值的位置
5) 插入元素:在指定的位置插入给定的值
6) 删除:删除指定位置的值或者是删除给定的值。
7) 遍历元素:从头到尾扫描线性表。*/
///创建带有头节点的链表Init
LinkListNode* InitLinkList(void)
{
LinkListNode* pHead = NULL;
pHead = (LinkListNode*)malloc(sizeof(LinkListNode));
if (pHead) {
pHead->pNext = NULL; //链表的最后一个结点next值为空
}
return pHead;
}
//求长度:求线性表中的元素的个数
int GetSizeLinkList(LinkListNode* pHead)
{
int n = 0;
while (pHead->pNext)
{
n++;
pHead = pHead->pNext;
}
return n;
}//取元素:取给定位置的元素值
//输入链表的头指针,要查找的编号,输出第pos个元素的地址
///pHead:头指针,pos 待查节点的序号
LinkListNode* GetLinkListNode(LinkListNode* pHead, int pos)
{
int j = 0;
LinkListNode* p;
p = pHead;//带头结点是在链表最前面的位置,不属于链表
if(pos == 0)
return NULL;
while (j < pos && p->pNext != NULL)
{
p = p->pNext;
j++;
}
if (pos == j)
return p;
else
return NULL;
}//查元素:查找给定元素值的位置
///找到就返回节点的地址,找不到就返回NULL
LinkListNode* LocateLinkList(LinkListNode* pHead, int objData)
{
LinkListNode* p;
p = pHead->pNext;//跳过头节点
while (p != NULL && p->data != objData)
{
p = p->pNext;
}
return p;}
//因为链表这种结构的内存是由程序员管理的,因此它的建立有一定的运算方法
///尾插法建立单链表
//arr:传入的顺序表,length:顺序表的长度
LinkListNode* Create_Rear_LkList(ElemType arr[], int length)
{
LinkListNode* pHead, *p, *q;
int i;//循环变量,用来遍历全部的顺序表pHead = (LinkListNode*)malloc(sizeof(LinkListNode));//头结点
//q是获得了当前链表的头节点
//q保存了pHead,同时通过q不断前移使得链表串联起来
q = pHead;
for (i = 0;i < length;i++)
{
//获得一个单链表的节点,将这个节点加入到有pHead指向的这个链表当中
//p获得一个可以加入链表的节点单元
p = (LinkListNode*)malloc(sizeof(LinkListNode));
p->data = arr[i];//将顺序表的内容存入单链表的节点q->pNext = p;//pHead一直指向链表头结点是不变的,通过q不断前移来串联链表
q = p;
}
p->pNext = NULL;
return pHead;}
///头插法建立单链表,在head与head->next之间不断插入新申请结点
LinkListNode* Create_Front1_LkList(ElemType arr[], int length)
{
LinkListNode* pHead, *p, *q;
int i;
pHead = (LinkListNode*)malloc(sizeof(LinkListNode));
pHead->pNext = NULL; //有头结点的空链表
q = pHead->pNext;
//头插的时候,必须逆序遍历顺序表
for (i = length - 1;i >= 0;i--)
{
p = (LinkListNode*)malloc(sizeof(LinkListNode));
p->data = arr[i];
p->pNext = q;//是的新加入的节点传入了上一个节点
pHead->pNext = p;//头节点指向了当前的新加入节点
q = pHead->pNext;//让q指向当前的节点
}
return pHead;
}
///头插法2
LinkListNode* Create_Front2_LkList(ElemType arr[], int length) {
LinkListNode* pHead, *p, *q;
//p是新加入节点,q是当前节点
int i;
q = NULL;
for (i = length - 1;i >= 0;i--)
{
p = (LinkListNode*)malloc(sizeof(LinkListNode));
p->data = arr[i];
p->pNext = q;
q = p;
}
pHead = (LinkListNode*)malloc(sizeof(LinkListNode));
pHead->pNext = q;
return pHead;
}///头插法建立
LinkListNode* Create_Front3_LkList(ElemType arr[], int length)
{
LinkListNode* pHead, *p;
int i;
pHead = (LinkListNode*)malloc(sizeof(LinkListNode));
pHead->pNext = NULL;
for (i = length - 1;i >= 0;i--)
{
p = (LinkListNode*)malloc(sizeof(LinkListNode));
p->data = arr[i];
p->pNext = pHead->pNext;
pHead->pNext = p; //pHead没有变化,pHead->pnext是不断变化的,始终作为当前节点的指针
}
//之所以我们的方法三可以节省方法一中的一个变量q
//原因是:pHead不发生变化,而pHead中的pNext始终作为当前节点的指针
//实际应用中采用的就是方法3
return pHead;
}/*
顺序表:12,33,44,76,89,90(逻辑上的顺序表)=>单链表
本例中,我们用数组表示这种顺序表
*/
//插入元素:在指定的位置插入给定的值
//在指定位置之后插入
void Insert_After_LkList(LinkListNode* ptr, ElemType x)
{
LinkListNode* s;
s = (LinkListNode*)malloc(sizeof(LinkListNode));
s->data = x;
s->pNext = ptr->pNext; //ptr代表当前结点, ptr->pNext代表当前结点的下一个结点
ptr->pNext = s; //s代表带插入结点
}//指定节点之前插入
void Insert_Before_LkList(LinkListNode* pHead, LinkListNode* ptr, ElemType x)
{
LinkListNode* s, *qPtr;
s = (LinkListNode*)malloc(sizeof(LinkListNode));
s->data = x;
qPtr = pHead;//qPtr是用来代替pHead的移动的,ptr是目标节点
while (qPtr->pNext != ptr)
{
qPtr = qPtr->pNext; //后移结点指针!!!
}
/*退出循环时候qPtr->pNext == ptr*/
s->pNext = ptr;
qPtr->pNext = s;
//因为链表是单向的,虽然我知道当前节点是ptr
//但是在语法层面上,我如果想知道ptr的前继节点只能从head遍历而来
//查到了当前节点的前继,才能使用后插的方法完成节点的加入
}
//删除:删除指定位置的值或者是删除给定的值。
//情形一:删除指定节点的后继结点
//情形二:删除第i个节点,假定头节点i=0
///删除指定节点ptr的后续节点
LinkListNode* Delete_After_LkList(LinkListNode* ptr)
{
LinkListNode* fptr;
//假定我们的顺序表A-》B-》C,我们要删除的是A的后续节点B,A-》C
fptr = ptr->pNext;// ptr是A,所以ptr的next是B,所以fptr是B
ptr->pNext = fptr->pNext;//ptr是A,fptr是B,所以fptr的next是C,所以ptr-next就变成C
return fptr;
}///删除第i个节点
LinkListNode* Delete_i_LkList(LinkListNode* pHead, int i)
{
LinkListNode*ptr, *qPtr = NULL;
ptr = GetLinkListNode(pHead, i - 1);//找到i的前继节点
if (ptr != NULL && ptr->pNext != NULL)
qPtr = Delete_After_LkList(ptr);
return qPtr;
}//遍历
void ShowLkList(LinkListNode* pHead)
{
LinkListNode* p = pHead->pNext; //跳过链表头结点,从链表第一个结点开始打印
while (p != NULL)
{
printf(" %d", p->data);
p = p->pNext;
}
}
main.c测试接口
#include "LinkList.h"
int main(void)
{
ElemType MySeq[] = { 1,2,3,4,5 };LinkListNode* pHead = Create_Rear_LkList(MySeq, 5);
printf("\n********显示当前单链表中的全部元素******\n");
ShowLkList(pHead);LinkListNode* pPos = GetLinkListNode(pHead, 2);
Insert_After_LkList(pPos, 999);
printf("\n********显示当前单链表中的全部元素******\n");
ShowLkList(pHead);Insert_Before_LkList(pHead, pPos, 666);
printf("\n********显示当前单链表中的全部元素******\n");
ShowLkList(pHead);//Delete_After_LkList(pPos);
Delete_i_LkList(pHead, 2);
printf("\n********显示当前单链表中的全部元素******\n");
ShowLkList(pHead);printf("\nList Size:%d", GetSizeLinkList(pHead));
getchar();
return 0;
}