单链表实现就地逆转
来源:互联网 发布:人工智能作业答案 编辑:程序博客网 时间:2024/04/30 12:52
在这里,我将展示用头插法的方法实现链表的就地逆转。原理是对于一个给定的链表,先将其头结点摘出来,接下来,依次将链表中的结点摘出来,用头插法插入到摘出来的头结点之后,直到将所有的结点都插入,那么就实现了链表的就地逆转。下面给的程序是c语言程序,可以在gcc里面运行出来。并且有详细的注释,因而在这儿就不再赘述类,看下面的程序。
注意:a.txt文件中的内容就是我们要逆转的数据,要跟我们的.c文件放在一起,否则就要将路径完整写出!!!
#include <stdio.h>#include <stdlib.h>//=====================================================//操作状态#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;//=====================================================//构造一个空的线性表LStatus 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;}//=====================================================//销毁线性表Lvoid 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;}//=====================================================//在当前位置之后插入数据元素eStatus 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;}//=====================================================//在表头插入数据元素eStatus 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 0
- 单链表实现就地逆转
- 单链表的就地逆转
- 单链表就地逆转
- 2.22-单链表就地逆转
- 带头结点单链表的就地逆转
- 带头结点单链表的就地逆转
- 链表就地逆转
- 单链表的实现(包括就地逆转单链表,表排序, 合并单链表、判断表是否有环)
- 单链表的实现(包括就地逆转单链表,表排序, 合并单链表、判断表是否有环)
- 单链表的创建,插入,删除以及就地逆转
- 单链表的就地逆转 -- 浙大《数据结构》第二版 例2.4
- 就地逆转输出链表
- 单链表,实现逆转
- 单链表的逆转实现
- java实现单链表逆转
- 2.21-顺序表就地逆转
- 链表的输入输出以及就地逆转
- 逆转单链表c#模拟实现
- VC使用中的一些总结(一)
- c语言头文件大全
- AArch64硬件平台整理
- Linux权限管理
- JSP session对象以及图片验证码的实现
- 单链表实现就地逆转
- 线段树
- ADB
- 提升程序效率的法宝
- 后序遍历首尾点(C语言版)
- float/double数据不显示成科学计数法
- 常用socket函数详解
- CF 601D(Acyclic Organic Compounds-字典树)
- 对Java文件进行jar打包成可执行文件