c语言实现逆转线性单链表,单链表实现就地逆转

#include

#include

//=====================================================

//操作状态

#define TRUE 1

#define FALSE 0

#define OK 1

#define ERROR 0

//=====================================================

// 操作状态类型

typedef int Status;

// 数据元素类型

typedef int ElemType;

//=====================================================

// 结点类型

typedef struct tag_LNode{

int data;

struct tag_LNode *next;

}LNode;

//=====================================================

// 链表类型(带头结点的单链表)

typedef struct {

int lenth; // 指示链表长度

LNode *head; // 分别指向头结点和最后一个结点的指针

LNode *current; // 指向当前被访问的结点的指针,初始位置指向头结点

} LinkList;

//=====================================================

//构造一个空的线性表L

Status InitList(LinkList *L)

{

L->head = (LNode *)malloc(sizeof(LNode));//开辟一个新的空间

if(!L->head) return ERROR; //空间开辟不成功

L->head->next = NULL; //初始化线性表L

L->lenth = 0;

L->current = L->head;

return OK;

}

//=====================================================

//销毁线性表L

void DestroyList(LinkList *L) //销毁线性表 L

{

LNode *p;

p = L->head; //p指向表头

while(p) //依次从表头开始删除每一个结点

{

L->head = L->head->next;//摘出p

free(p); //删除p

p = L->head; //又将p指向表头

}

}

//=====================================================

//清空线性表的元素

void ClearList(LinkList *L)

{

LNode *p;

while(L->head->next) //删除除了表头的所有结点

{

p = L->head->next; //p指向表头的下一个结点

L->head->next = p->next;//摘出结点p

free(p); //删除p

}

}

//=====================================================

// 改变当前指针指向第i个结点

Status LocatePos(LinkList *L, int i )

{

int k;

k = 0;

L->current = L->head; //初始化当前指针指向头指针处

while(L->current->next && k < i)//移动当前指针,直到指向第i个位置结束

{

L->current = L->current->next;

k++;

}

if(k != i) return ERROR;

return OK;

}

//=====================================================

//在当前位置之后插入数据元素e

Status InsertAfter(LinkList *L, ElemType e)

{

LNode *s;

if(!L->current) return ERROR;//当前指针为空,就返回错误

s = (LNode *)malloc(sizeof(LNode));//给s开辟新空间

if(!s) return ERROR; //s开辟空间失败

s->data = e; //将e赋给s->data

if(L->current->next == NULL)//如果当前指针是最后一个,那么直接插入到最后即可

L->current->next = s;

else //当前指针不在最后时,我们就在当前指针之后插入

{

s->next = L->current->next;

L->current->next = s;

}

L->lenth++; //插入一个结点后,表的长度要加1

return OK;

}

//=====================================================

//在表头插入数据元素e

Status InsertHead(LinkList *L, ElemType e)

{

LNode *p;

p = (LNode *)malloc(sizeof(LNode));//给p开辟新空间

if(!p) return ERROR; //p开辟空间失败

p->data = e; //将e赋给p->data

p->next = NULL;

p->next = L->head->next; //在表头插入结点p

L->head->next = p;

L->lenth++;

return OK;

}

//=====================================================

//输出单链表的数据

void PrintOut(LinkList L)

{

LNode *p;

printf("链表有%d个元素:",L.lenth);

p = L.head->next;

while(p) //当p非空时,输出p的数据值

{

printf("%d ", p->data);

p = p->next;

}

}

//=====================================================

//在表中查找数据元素e,让当前指针(current)指向该结点

Status LocateElem(LinkList *L, ElemType e)

{

LNode *p;

p = L->head->next;

while(p)

{

if(p->data == e) //依次判定该结点的数据是不是e

{

L->current = p; //将当前指针指向p

return OK;

}

p = p->next;

}

return ERROR;

}

//=====================================================

//求线性表的长度

int ListLenth(LinkList L)

{

return L.lenth; //直接返回线性表L的长度即可

}

//=====================================================

//线性表就地逆转(前插法)

void ListReverse(LinkList *L)

{

LNode *p,*q;

p = L->head->next; //p指向表头的下一个结点

L->head->next = NULL; //摘出表头

while(p) //依次用前插法插入结点

{

q = p->next; //q指向p的下一个结点,将p摘出来

p->next = L->head->next;//将摘出来的p出入到表头的后面

L->head->next = p;

p = q; //将p指向q指向的位置

}

}

//=====================================================

int main(int argc,char* argv)

{

FILE *fp; //文件指针

LinkList L; //线性表

ElemType e;

int j; //j作为后面选项的变量

int i = 1; //i作为while循环的判定变量

if((fp = fopen("a.txt", "r")) == 0)//打开文件“a.txt”,r表示可读的意思

{

printf("打开文件失败");

return -1;

}

if(!InitList(&L)) //初始化链表L

{

printf("初始化链表失败\n");

return -2;

}

LocatePos(&L, 0); //改变当前指针指向表的头结点

while(1) //读入数据并插入到表中

{

if(fscanf(fp, "%d", &e) == EOF)//文件中的数据读数据到单链表L,知道读到文件最后,再跳出while循环,EOF是end of file 的意思

break;

InsertAfter(&L, e);

}

while(i)

{

printf("1.查看原始链表中的数据\n");

printf("2.输出链表长度\n");

printf("3.查找链表中的元素\n");

printf("4.逆转该链表,并输出逆转后的数据\n");

printf("5.销毁链表\n");

printf("0.退出!\n");

printf("选择你要进行的操作\n");

scanf("%d", &j); //输入选项

printf("\n");

switch(j) //使用了switch-case来对选择不同的选项进行不同的操作

{

case 1: //输出单链表L的数据

printf("\n原始链表\n");

PrintOut(L); //输出原始链表中的数据

printf("\n\n");

break;

case 2: //链表长度

printf("链表长度:%d\n", ListLenth(L));//调用了链表长度的函数

printf("\n");

break;

case 3: //查找链表元素

printf("输入要查找的数: ");

scanf("%d", &e);

if(LocateElem(&L, e))//LocateElem(&L,e)是调用定位函数,将当前指针定位到元素e的位置

printf("元素%d在链表中\n", L.current->data);

else

printf("元素%d不在链表中\n", e);

printf("\n");

break;

case 4: //链表就地逆转

printf("\n原始链表\n");

PrintOut(L); //输出原始链表里面的元素

printf("\n\n");

ListReverse(&L);//调用逆转链表的函数

printf("\n逆转链表\n");

PrintOut(L);

printf("\n\n");

break;

case 5: //销毁链表L

DestroyList(&L);//调用销毁链表的函数

printf("\n");

break;

case 0:

printf("\n结束!\n");

i = 0; //i = 0使得跳出整个while循环,结束程序

printf("\n");

}

}

return 0;

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值