希望对你有帮助!
#include <stdio.h>
#include <malloc.h>//分配内存函数所需包含的头文件
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status//类型定义,即给一个类型定义另一个名字,下同
typedef int ElemType
//链表结点定义
typedef struct Lnode{
ElemType data
struct Lnode *next//这里采用的是递归定义,定义一个指向该结点类型的指针next,同时next又是结点的数据成员
}Lnode
typedef Lnode *LinkList//给Lnode*取一个名字LinkList,即LinkList是指向该结点类型的指针类型,它定义的变量均为指向该结点的指针
//初始化链表
Status InitList(LinkList &L) //这里的&是C++中的引用,严格来说是不允许这样用的,但教材上都这么用,所以我也这样用了,这无关紧要
{ LinkList p//定义一个结点指针p
p=(LinkList)malloc(sizeof(Lnode))//给p分配一个结构体大小的空间
if(p==NULL) return ERROR//如果p为空则表示分配不成功,返回错误
L=p //否则将p赋给L
L->next=NULL//并将头结点的next域置为空
return OK
}
//创建链表
Status CreatList(LinkList &L)
{ int i,len
ElemType x
LinkList p,q
printf("输入链表的长度:")
scanf("%d",&len)
printf("输入链表的元素:")
i=0q=L//将头结点赋给结点指针q
//使用循环将新创建的结点插入到链表的尾部
while(i<len)
{ p=(LinkList)malloc(sizeof(Lnode))//给新结点分配空间
scanf("%d",&x)
p->data=x//将数据放在新结点的data域中
q->next=p//并将新结点连在q即链表头结点的后面
q=p//再将p赋给q用来移动q,循环添加
i++//i也不断自增直至i=len
}
q->next=NULL //循环结束后要将最后一个结点的next域置为空以使该链表能正常结束
return OK
}
//获取链表长度
int ListLength(LinkList L)
{ int len=0
LinkList p
p=L->next//将头结点的下一个结点(注意:头结点的数据域是不存放数据的)赋给p
while(p)//循环移动p直至p的指向为空,即p的next域为NULL时结束循环
{ len++//用len计数
p=p->next}
return (len)
}
//取链表中的元素
Status GetList(LinkList L,int i,ElemType &e)
{ int j
LinkList p
if(i<1)return ERROR//判断i是否小于1,上面说过链表头结点不存放数据,存放数据的结点从头结点之后的第一个结点开始
j=0
p=L//将头结点赋给p
while(p->next!=NULL&&j<i) //当p的next域不为空且j<i继续循环
{ p=p->next//不断移动p
j++
}
//退出循环有两种情况,一是p的next为空即链表结束,二是循环到了目标位置,所以下面要判断是否循环到目标位置
if(j==i) //是则取目标位置的数据并赋给变量e,由于e也是引用类型,所以可以实现双向传递
return ERROR
}
//在链表中查找元素
int SearchList(LinkList L,ElemType e)
{
int pos=1
LinkList p=L->next//将链表的第一个数据结点赋给p
if(!p) return ERROR//如果p为空则返回错误
while(p){ //当p不为空时执行循环
if(p->data==e){
break//如果找到元素则退出循环
}
else p=p->next//否则移动指针p
pos++//位置不断自增
}
return pos
}
//插入数据
Status InsertList(LinkList &L,int i,ElemType e)
{ int j
LinkList p,q
if(i<1)return ERROR//同样要判断所给插入的位置是否正确,即如果i<1,则返回错误
j=0
p=L
while(p->next!=NULL&&j<i-1)//这里要将p循环到目标位置的前一个结点处,然后将新结点插入到p所指结点的后面
{ p=p->next
j++}
if(j==i-1) //这里也要判断,条件为真则执行
{ q=(Lnode *)malloc(sizeof(Lnode))//创建新结点
q->data=e//并将要插入的数据存放在新结点的数据域中
q->next=p->next//将q的next指针所指的结点赋给p的next
p->next=q//然后将新结点q赋给p的next,从而实现了结点的插入。如果你觉得难理解,画图表示就明白了
return OK}
return ERROR
}
//删除数据
Status DeleteList(LinkList &L,int i,ElemType &e)
{ int j
LinkList p,q
if(i<1)return ERROR
j=0
p=L
//循环到目标位置的前一个结点处,用条件j<i-1控制
while(p->next!=NULL&&j<i-1)
{ p=p->next
j++}
//如果p的next为空则表示所给的位置不正确
if(p->next==NULL)
else //否则执行删除 *** 作
{ q=p->next//将p的next所指的结点赋给q,q才是要删除的结点!
p->next=q->next//并将q的next域赋给p的next域
e=q->data//将要删除的结点的数据赋给变量e
free(q)//释放结点指针,即从链表中删除了该结点
return OK}
}
//输出链表
void PrintList(LinkList L)
{
LinkList p
p=L->next//将链表的第一个数据结点赋给p
printf("链表中的元素为:")
while(p){//如果p为空则结束循环
printf("%4d",p->data)//输出p所指的结点的数据域
p=p->next//移动指针p
}
printf("\n")
}
/*注意:上面几个函数在处理链表时都会定义一个结点指针p并使其指向头结点,即LinkList p=L,
之所以这样做是因为头结点唯一标识了该链表的存在,而且通过头结点遍历整个链表,所以不能通过移动头结点遍历链表*/
void main()
{
ElemType i,e
LinkList L
InitList(L)
CreatList(L)
printf("输入要取元素的位置:")
scanf("%d",&i)
GetList(L,i,e)
printf("第%d个位置的元素是:%d\n",i,e)
printf("输入要插入元素的位置及元素值:")
scanf("%d%d",&i,&e)
InsertList(L,i,e)
printf("已插入元素%d在第%d个位置!\n",e,i)
PrintList(L)
printf("输入你要查找的元素值:")
scanf("%d",&e)
i=SearchList(L,e)
printf("你要找的元素%d在链表的第%d个位置!\n",e,i)
printf("输入要删除的位置:")
scanf("%d",&i)
DeleteList(L,i,e)
printf("已删除第%d个元素的位置%d!\n",i,e)
PrintList(L)
}
int Insert_LinkList_End(LinkList L,int x){
LinkList p = head->next//head是表头
for(x=0p->next!=NULLp=p->next,x++)
p->next=L
return x
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)