数据结构
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
//循环链表初始化
LNode* init_list();
//函数返回值是头结点地址
//在链表的第ii位置插入元素ee
int Insert_Elem(LNode * LL,unsigned int ii,ElemType* ee);
//打印整个链表数值
void printlinklist(LNode * LL);
//计算整个链表的长度
int LengthList(LinkList LL);
//判断链表是否为空
int IsEmpty(LinkList LL);
// 获取链表中第ii个结点,成功返回结点的地址,失败返回空。
// 注意,ii可以取值为0,表示头结点。
LNode *LocateNode(LinkList LL, unsigned int ii);
// 查找元素ee在链表LL中的结点地址,如果没找到返回NULL,否则返回结点的地址。
LNode *LocateElem(LinkList LL, ElemType *ee);
// 在指定结点pp之后插入元素ee,返回值:0-失败;1-成功。
int InsertNextNode(LNode *pp, ElemType *ee);
// 在指定结点pp之前插入元素ee,返回值:0-失败;1-成功。
int InsertPriorNode(LNode *pp, ElemType *ee);
void main()
{
int i=0;
ElemType ee;
LinkList LL=init_list();
//在初始化循环链表之后使用这样的赋值其实
//和pp=pp->next作用是一样的,这是因为只有一个头结点
LNode* pp=LL->next;
printf("判断链表是否为空\n");
printf("%d\n",IsEmpty(LL));
printf("LL=%p\n",LL);
printf("在表中插入元素1,2,3,4,5,6,7,8,9\n");
for(i=1;i<10;i++)
{
ee=i;
Insert_Elem(LL,i,&ee);
}
printf("打印链表的全部数值\n");
printlinklist(LL);
pp=pp->next;
pp=pp->next;
ee=15;InsertPriorNode(pp,&ee);
printf("打印链表的全部数值\n");
printlinklist(LL);
printf("判断链表是否为空\n");
printf("%d\n",IsEmpty(LL));
printf("打印链表的全部数值\n");
printlinklist(LL);
printf("计算链表的长度\n");
printf("链表的长度为 %d \n",LengthList(LL));
//获取第5个元素的地址
pp=LocateNode(LL,5);
//显示第五个元素的数值为
printf("第5个元素的数值为%d\n",pp->next);
//查找元素0的位置,这个时候没有插入元素0
ee=0;LocateElem(LL,&ee);
//插入元素0
ee=0;InsertNextNode(LL,&ee);
//对应元素位置节点查找
LocateElem(NULL,&ee);
ee=0;LocateElem(LL,&ee);
ee=1;LocateElem(LL,&ee);
ee=2;LocateElem(LL,&ee);
ee=3;LocateElem(LL,&ee);
ee=4;LocateElem(LL,&ee);
ee=5;LocateElem(LL,&ee);
ee=6;LocateElem(LL,&ee);
ee=7;LocateElem(LL,&ee);
ee=8;LocateElem(LL,&ee);
ee=9;LocateElem(LL,&ee);
ee=10;LocateElem(LL,&ee);
printf("打印链表的全部数值\n");
printlinklist(LL);
pp=pp->next;
ee=15;InsertPriorNode(pp,&ee);
printf("打印链表的全部数值\n");
printlinklist(LL);
system("pause");
}
//循环链表初始化
LNode* init_list()
{
//定义头结点为一个LNode*类型的指针,并且分配给他LNode类型大小的内存
LNode* head=(LNode*)malloc(sizeof(LNode));
//如果分配内存失败,那么malloc()返回的就是一个空指针
if(head==NULL)
{
printf("内存空间不足");
return NULL;
}
head->next=head;//头节点的指针指向自己
//返回头结点地址
return head;
//这样说来头结点好像没有元素,那我可不可以自己给他添加一个元素呢
//打印一下试试
//-842150451
//如果直接打印他的值就是上面的数值
//试试给他赋值
//赋值可以正常赋值
}
//插入数值函数 返回0插入成功,返回1插入失败
int Insert_Elem(LinkList LL,unsigned int ii,ElemType* ee)
{
//这款编辑器只支持在开头定义变量
//要不然会报非法的错误
unsigned int kk=1;
LNode* pp=NULL;
LNode* tem=(LNode*)malloc(sizeof(LNode));
if(LL==NULL || ee==NULL){printf("链表或者元素为空");return 0;}
if(ii<1) {printf("插入位置不合法,应该ii>=1");return 0;}
if(ii==1)
{
pp=LL;
}
else
{
pp=LL->next;//这里不能直接写成pp=pp->next 因为这个时候pp连初始值都没有
//如果这里写的是pp=pp->next;
//pp没有赋值为NULL的时候这个窗口会直接消失
//pp赋值为NULL的时候会多停留一会
//主要原因是这样pp的值指向不明确
//然后崩溃了
while(pp!=LL && kk<ii-1)
{
pp=pp->next;
kk++;
}
if(pp==LL){printf("插入位置超过表长");return 0;}
}
if(tem==NULL){printf("内存空间不足");return 0;}
tem->data=*ee;
//指针处理
tem->next=pp->next;
pp->next=tem;
return 1;
}
//打印所有数值的函数
void printlinklist(LNode * LL)
{
LNode* pp=LL;
pp=pp->next;
while(pp!=LL) {printf(" %d ",pp->data); pp=pp->next;}
}
//销毁链表
void DestroyList1(LinkList LL)
{
LNode *head=LL;
LNode *tem=NULL;
LL=LL->next;
while(tem!=LL)
{
tem=LL->next;
free(tem);
LL=tem;
}
free(head);
return;
}
// 求链表的长度,返回值:>=0-表LL结点的个数
int LengthList(LinkList LL)
{
LNode* pp=LL;
int length=0;
//从有数据的节点开始计算
pp=pp->next;
while(pp!=LL){length++; pp=pp->next;}
return length;
//不使用临时变量来计算链表的长度
//这个方法理论上是没有问题的,但是在这里不能正确的使用
//我觉得应该是编译器的问题
//这里用的是VS2010
//if(LL==NULL)
// return 0;
//else
// return LengthList(LL->next)+1;
// 不使用临时变量,如何计算链表(包括头结点)的长度?
//if (LL==NULL) return 0;
//return LengthList(LL->next)+1;
}
// 判断链表是否为空,返回值:0-非空或失败,1-空。
int IsEmpty(LinkList LL)
{
if(LL==NULL) return 0;
if(LL->next==LL) return 1;
return 0;
}
// 获取链表中第ii个结点,成功返回结点的地址,失败返回空。
// 注意,ii可以取值为0,表示头结点。
LNode *LocateNode(LinkList LL, unsigned int ii)
{
unsigned int i=0;
LNode* pp=LL;
if(LL==NULL) {printf("链表为空");return NULL;}
for(i=0;i<ii;i++)
{
pp=pp->next;
if(pp==LL){printf("位置超过表长"); return NULL;}
}
printf("从头结点开始算起,第%d个节点地址为%p\n",ii,pp);
return pp;
}
// 查找元素ee在链表LL中的结点地址,如果没找到返回NULL,否则返回结点的地址。
LNode *LocateElem(LinkList LL, ElemType *ee)
{
LNode* pp=LL;
if(LL==NULL){printf("链表为空\n"); return NULL;}
pp=pp->next;
while(pp!=LL)//循环链表,循环到头节点时代表当前的链表已经遍历
{
if(pp->data==*ee){printf("找到元素地址 %p \n",pp); return pp;}
pp=pp->next;
}
printf("没有找到链表之中对应的元素\n");
return NULL;
}
// 在指定结点pp之后插入元素ee,返回值:0-失败;1-成功。
int InsertNextNode(LNode *pp, ElemType *ee)
{
LNode * newlnode=(LNode*)malloc(sizeof(struct LNode));
if(pp==NULL){printf("节点为空无法插入\n"); return 0;}
//对新生节点赋值
newlnode->data=*ee;
//节点插入到当前之后
newlnode->next=pp->next;
pp->next=newlnode;
printf("节点插入成功\n");
printf("节点地址为 %p \n",newlnode);
return 1;
}
// 在指定结点pp之前插入元素ee,返回值:0-失败;1-成功。
int InsertPriorNode(LNode *pp, ElemType *ee)
{
LNode * tem=(LNode*)malloc(sizeof(struct LNode));
if(pp==NULL){printf("节点为空无法插入\n"); return 0;}
if(tem==NULL){printf("新的节点创建失败\n"); return 0;}
//节点插入操作
//把pp节点的元素的和指针赋值到tme中
memcpy(&tem->data,&pp->data,sizeof(ElemType));
tem->next=pp->next;
//对tem节点赋值
pp->data=*ee;
pp->next=tem;
printf("前向节点插入成功\n");
return 1;
}