一:使用简介
使用c语言实现了单链表的基本操作,代码共有四个文件,两个头文件是常用的,后两个分别是主函数,和对链表的基本操作函数,倒入时候,须将四个文件放在同一个目录下。
二:心得
在书写过程中,主要错误集中在指针的使用上,通过此次编程,对于指针的认识更加深刻,头结点的存在,更大意义上是为了简化指针的操作。
比如在初始化创建头结点的时候,需要改变头指针的指向,众所周知,在函数中改变头指针,必须要传入头指针的地址。如果没有头结点,后期的创建,插入,删除等操作可能都需要改变头指针,显然,每次都传入头指针地址(相当于指针的指针),不便于代码的易读性。如果有了头结点,这个繁琐的问题很轻易地解决了。后期的操作只需要改变头结点的指针域,除了在初始化的时候,需要改变头指针的地址(使其指向头结点),其他操作无需改变,当然在这些操作之前,必须要对链表进行初始化(创建头结点)。
#include
#include
#include
#include
#include
//常用的表示函数结果状态代码
#define OK1
#define ERROR0
typedef int Status ; //返回true or false
//定义链表的结构体
typedef struct Lnode{
Elemtype data;
struct Lnode* next;
}LNODE,*Plist;
//对链表进行的一系列操作
//初始化链表
Status InitList(Plist *p){
//创建头结点,使头指针指向头结点(头指针的指向要改变,所以要修改头指针)
*p=(Plist)malloc(sizeof(LNODE));
if(!(*p)){
//内存分配失败,程序退出
exit(OVERFLOW);
}
//将头结点的指针域置为空,*p为结构体指针,对结构体成员的引用使用->,如果是结构体,直接使用.引用成员
(*p)->next=NULL;
return OK;
}
//销毁单链表,销毁头结点,以及其后面所有有效节点,同时头指针要指向空,防止后面的程序不小心使用
//该过程改变了头指针的指向,所以需要传入头指针的地址,注意,在该过程中,只是修改了头指针的指向,
Status DestroyList(Plist* p){
//每次使用头指针时候,要赋值,保留原来的位置
Plist L=*p;
Plist q;
//如果指针不为空,就一直释放节点
while(L){
q=L->next;
free(L);
L=q;
}
//使头指针指向空
*p=NULL;
return OK;
}
//清除单链表,只是释放有效节点,不释放头结点
Status clearList(Plist p){
//P指向头结点,L指向第一个有效节点
Plist L=p->next,q;
//循环释放节点,知道最后的节点
while(L){
q=L->next;
free(L);
L=q;
}
//头结点的指针域指向空
p->next=NULL;
return OK;
}
//判断链表是否为空
Status EmptyList(Plist p){
int i=0;
Plist L=p->next;
while(L){
i++;
L=L->next;
}
if(i>0){
return OK;
}
return ERROR;
}
//判断链表里面的数据个数
int ListLength(Plist p){
int i=0;
//指向第一个有效节点的指针
Plist L=p->next;
while(L){
i++;
L=L->next;
}
return i;
}
//使用头插法创建单链表,该方法使用前,必须要初始化节点,该方法得到的数据是逆序的,n为要插入的数据个数
//头插法每次在头结点后面插入数据,不改变头指针的指向,所以不要传入头指针的地址
Status CreateList(Plist p,Elemtype e){
//L指向头结点
Plist L=p;
//每次插入的新数据都是第一个有效数据,每次需要修改的只是头指针
Plist node=(Plist)malloc(sizeof(LNODE));
if(!node) exit(OVERFLOW);
node->data=e;
node->next=L->next;
L->next=node;
//printf("插入数据%d\n",e);
return OK;
}
//获取某位置的数据
Status GetElem(Plist p,int i,Elemtype* e){
Plist L=p->next;
int j=1;
//判断该位置是否合理
if(i<1 i="">ListLength(p)){
return ERROR;
}
//找到该位置
while(L&&jnext;
j++;
}
*e=L->data;
return OK;
}
//获取某数据所在位置
int LocateElem(Plist p,Elemtype e){
//L指向第一个有效数据
Plist L=p->next;
int i=1;
while(L){
if(L->data==e){
break;
}
L=L->next;
i++;
}
if(i>ListLength(p)){
//数据不存在
return ERROR;
}
return i;
}
//对链表进行插入
Status InsertList(Plist p,int i,Elemtype e){
int j=0;
//L指向头结点
Plist L=p;
//判断插入位置是否合理
if(i<1 i="">ListLength(L)+1){
return ERROR;
}else{
//寻找插入点的前一个位置
for(;jnext;
}
//分配新节点
Plist node=(Plist)malloc(sizeof(LNODE));
if(!node) exit(OVERFLOW);
node->data=e;
//执行插入
node->next=L->next;
L->next=node;
return OK;
}
}
//对链表数据进行删除,并返回删除的数据
Status DeletList(Plist p,int i,Elemtype* e){
int j=0;
//L指向头结点
Plist L=p;
//判断链表是否为空
if(!ListLength(p)){
return ERROR;
}else if(i<1 i="">ListLength(L)){
//判断删除位置是否合理
return ERROR;
}else{
//寻找删除点的前一个位置
for(;jnext;
}
//保存将要删除的节点
Plist node=L->next;
*e=node->data;
L->next=node->next;
//释放节点
free(node);
return OK;
}
}
//显示链表的操作,传入链表的头指针
void showList(Plist p){
//指向第一个有效节点的指针
Plist q=p->next;
while(q){
printf("%d\n",q->data);
q=q->next;
}
}
1>1>1>
#include "c-1.h"
//定义抽象数据的数据类型
typedef int Elemtype;
#include "c-2.h"
#include "operate.cpp"
int main(){
//创建一个结构体指针,使其指向空,该指针是链表的头指针
Plist p=NULL;
int len=0,i=0;
Elemtype e,val;
//*******************初始化链表
if(InitList(&p)){
printf("初始化成功\n");
}
//******************头插法创建链表
printf("请输入链表长度\n");
scanf("%d",&len);
for(i=0;i
printf("请输入第%d个数据:\n",i+1);
scanf("%d",&e);
CreateList(p,e);
}
printf("链表长度是%d\n",ListLength(p));
printf("遍历链表:\n");
//显示链表
showList(p);
//******************尾插法创建链表
/*printf("请输入链表长度\n");
scanf("%d",&len);
Plist q=p;
while(idata=e;
node->next=NULL;
q->next=node;
//保存最后一个节点的指针,用于下次在结尾添加数据
q=node;
i++;
}
printf("链表长度是%d\n",ListLength(p));
printf("遍历链表:\n");
//显示链表
showList(p);*/
//********************销毁单链表
/*DestroyList(&p);
if(p==NULL){
printf("销毁成功");
}else{
printf("销毁失败");
}*/
//*************清空链表,有效节点都被释放
/*clearList(p);
printf("链表长度是%d\n",ListLength(p));*/
//**********************执行插入操作
/*if(InsertList(p,3,7)){
printf("插入成功\n");
}else{
printf("插入失败\n");
}*/
//**********************执行删除操作
/*if(DeletList(p,3,&val)){
printf("删除成功,删除数据是%d\n",val);
}else{
printf("删除失败\n");
}*/
//**********************获取某位置的数据
if(GetElem(p,4,&val)){
printf("查找成功,查找数据是%d\n",val);
}else{
printf("查找失败\n");
}
//**********************获取某数据所在的位置
if(LocateElem(p,3)){
printf("查找成功,所在位置是%d\n",LocateElem(p,3));
}else{
printf("数据不存在,查找失败\n");
}
//showList(p);
return 0;
}