单链表逆置 c++
c语言编程acm链表的逆置
标题:C语言编程ACM:链表的逆置一、概述ACM(Advanced Computing Machinery)竞赛是计算机科学领域最负盛名的竞赛之一,要在ACM竞赛中获得优异的成绩,熟练掌握C 语言编程技术是必不可少的。
本文将讨论C语言编程中常见的ACM题目之一:链表的逆置。
二、链表的基本概念1.链表的定义链表是一种线性表的物理存储单位,由一个个节点组成,每个节点包含数据元素和下一个节点的指针。
链表中的数据元素可以是任意类型。
2.链表的基本操作在C语言中,链表的基本操作包括插入节点、删除节点、查找节点等。
而链表的逆置就是将链表中的节点顺序颠倒。
三、链表的逆置方法在C语言中,链表的逆置可以采用多种方法实现。
1.迭代法迭代法是最直接的方法,具体步骤如下:(1)初始化三个指针,分别指向当前节点、前一节点、后一节点。
(2)遍历链表,将当前节点的指针指向前一节点。
(3)更新前一节点和当前节点的位置。
(4)遍历结束后,前一节点指向NULL,表示逆置完成。
2.递归法递归法是一种更为巧妙的方法,具体步骤如下:(1)递归遍历链表,直至到达链表尾部。
(2)从链表尾部开始,逐一修改每个节点的指针指向。
(3)递归结束后,链表即被逆置。
四、链表逆置的C语言实现以下是链表逆置的C语言实现代码,以迭代法为例:```ctypedef struct Node {int data;struct Node* next;} Node;Node* reverseList(Node* head) {Node *prev = NULL, *curr = head, *next = NULL; while (curr) {next = curr->next;curr->next = prev;prev = curr;curr = next;}return prev;}```五、实例分析假设有一个链表的头指针为head,包含数据元素1、2、3、4、5。
单链表原地逆置算法
单链表原地逆置算法单链表是一种常见的数据结构,其操作包括插入、删除和查找等。
在实际应用中,有时需要将单链表进行逆置操作。
逆置操作的实现方式有多种,其中一种是原地逆置。
原地逆置是指在不使用额外空间的情况下,将单链表逆置。
具体实现方式如下:1. 定义三个指针:pre、cur、next,分别指向当前节点的前一个节点、当前节点和当前节点的后一个节点。
2. 将cur指向单链表的头节点。
3. 遍历链表,每次迭代,将cur指向的节点的next指针指向pre,然后依次将pre、cur、next往后移动一个节点。
4. 当遍历完成后,将单链表的头节点指向pre,即可完成原地逆置。
代码实现如下:```struct ListNode* reverseList(struct ListNode* head){ struct ListNode* pre = NULL;struct ListNode* cur = head;struct ListNode* next = NULL;while(cur != NULL){next = cur->next;cur->next = pre;pre = cur;cur = next;}head = pre;return head;}```需要注意的是,在实现原地逆置时,需要特别注意链表中间节点的next指针指向前一个节点后,后续节点的next指针会断开。
因此,在移动指针时需要先记录下一个节点的位置,避免指针错误。
原地逆置是一种高效的单链表逆置算法,其时间复杂度为O(n),空间复杂度为O(1)。
在实际应用中,可以使用该算法实现链表的逆置操作。
C语言链表逆序方法技巧
C语言链表逆序方法技巧C语言链表逆序方法技巧C语言有丰富的数据结构和运算符。
包含了各种数据结构,如整型、数组类型、指针类型和联合类型等,用来实现各种数据结构的运算。
下面是店铺为大家搜索整理的`C语言链表逆序方法技巧,希望大家能有所收获,简洁的做法是遍历链表,元素进栈,遍历的同时销毁原来的链表。
元素出栈,建立新链表。
高效的是,用指向链表结点指针的指针操作直接首尾交换指针值(两两进行)一般的是前插法实际上根本就不用插入,一次遍历就可以完成了。
链表的逆序,必将涉及到两个以上指针,一般用三个指针,下面是一个人的程序:struct List1 *reverse(List1 *h) //h为链表的头指针{struct List1 *p,*v1,*v2;v2=h;v1=NULL;while( v2!=NULL ){p=v2->pNext;v2->pNext=v1;v1=v2;v2=p;}return v1;}另一个人的:struct IntNode* res(struct IntNode* h){struct IntNode *s, *s1;s = h;h = NULL;while (s){s1 = s;s = s->next;s1->next = h;h = s1;}return h;}算法都是一致,但顺序不一样,这直接点明了链表操作的核心——顺序,链表的算法主要难在顺序上。
逆序操作中,要将一个指针指向前一个节点,中间必然断开,这就需要两个指针指向断开处的一前一后。
上面两个程序都是这样,不同在于指针移动的位置。
下载全文。
单链表的就地逆置问题
以上是我对单链表就地逆置的一些理解,希望对各位有所帮助版浏览器
单链表的就地逆置问题
问题描述:编写一个单链表的成员函数,实现对带头结点的单链表的就地逆置操作 涉及变量:position:Node型变量,用于存放尚未反转的结点中首结点的位置
temp:用于标记执行反转操作的结点 涉及教材:《数据结构——Java语言描述(第2版)》 清华大学出版社 大致思路: 将头结点的指针域设为空,再将原来的结点从首结点开始依次连接在头结点之后,即可将原来位置倒置
单链表的逆置c语言
以下是使用C语言实现单链表逆置的示例代码:c复制代码#include<stdio.h>#include<stdlib.h>// 定义链表节点结构体struct ListNode {int val;struct ListNode *next;};// 定义函数用于链表逆置struct ListNode* reverseList(struct ListNode* head) {struct ListNode *prev =NULL;struct ListNode *curr = head;while (curr != NULL) {struct ListNode *next = curr->next;curr->next = prev;prev = curr;curr = next;}return prev;}// 创建链表并逆置int main() {struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode));head->val = 1;head->next = NULL;struct ListNode *node2 = (struct ListNode*)malloc(sizeof(struct ListNode));node2->val = 2;node2->next = NULL;struct ListNode *node3 = (struct ListNode*)malloc(sizeof(struct ListNode));node3->val = 3;node3->next = NULL;head->next = node2;node2->next = node3;struct ListNode *newHead = reverseList(head);while (newHead != NULL) {printf("%d ", newHead->val);newHead = newHead->next;}return0;}在上面的代码中,我们首先定义了链表节点结构体,其中包含一个整数值和一个指向下一个节点的指针。
C语言实现单链表逆置
什么单链表的逆置问题描述设计一个程序,实现单链表的逆置。
一、需求分析⑴按程序提示输入并创建一个单链表,带有头结点⑵可自定义链表的长度,可自定义链表储存的数据类型,注意更改相应的输入输出方式⑶实现单链表的逆置,直观地输出结果二、概要设计为实现上述程序功能,需创建以下抽象数据类型:ADT LinkList {数据对象:D={ai|ai∈(0,1,…,9),i=0,1,2,…,n,n≥0}数据关系:R={<ai-1,ai>|ai-1,ai∈D,i=1,2,…,n}基本操作:InitList(&L)操作结果:初始化一个链表L。
CreatList(L,L_Length)初始条件:链表L已存在。
操作结果:创建一个长度为L_Length的单链表。
InverseList(L)初始条件:链表L已存在。
操作结果:将单链表逆置。
DisplayList(L)初始条件:链表L已存在。
操作结果:销毁链表L。
} ADT LinkList本程序包含四个模块,即1)主程序模块,接受命令2)初始化及链表创建模块,按要求创建链表3)单链表逆置模块,实现单链表的逆置4)显示模块,输出结果三、详细设计(C语句,而非伪码)1.元素类型、节点类型和指针类型的定义typedef int Status;//函数状态类型typedef int ElemType;//元素类型typedef struct node{ElemType data;struct node *next;}Node,*LinkList;//节点类型、2.基本操作和所需调用的函数//初始化一个链表Status InitList(LinkList *L){*L=(LinkList)malloc(sizeof(node));if(!(*L)) exit(-2);//内存分配失败(*L)->next=NULL;return 1;}//在初始化的基础上按顺序创建一个链表Status CreatList(LinkList L,int n){LinkList p=L;int i;for(i=0;i<n;i++){(p->next)=(LinkList)malloc(sizeof(node));if (!(p->next)) exit(-2);//内存分配失败scanf("%d",&p->next->data);p=p->next;}p->next=NULL;return 1;}//依次输出单链表中的各个元素Status DisplayList(LinkList L){LinkList p;p=L->next;while(p){printf("%5d",p->data);p=p->next;}printf("\n");return 1;}//逆置1(递归方法)LinkList Ieverse(LinkList pre, LinkList cur) {LinkList head;if(!cur)return pre;head =Ieverse(cur, cur->next);cur->next = pre;return head;}//逆置2(就地逆置)Status Ieverse(LinkList L) {LinkList last = L->next;LinkList first ;while(last->next){first = L->next;L->next=last->next;last->next=L->next->next;L->next->next=first;}return 1;}3.主函数及功能的实现void main(){LinkList L;int L_Length;InitList(&L);//初始化链表printf("请输入单链表的长度:\n");scanf("%d",&L_Length);if(L_Length < 1) exit(-1);//长度不符合要求printf("请依次输入各个元素的值:\n");CreatList(L,L_Length);//按输入数据创建链表DisplayList(L);//显示原单链表//L->next=Ieverse(NULL,L->next);此语句可调用递归方法实现链表的逆置//Ieverse(L);//实现单链表的就地逆置printf("After reversing!\n");DisplayList(L);//显示逆置后的链表}四、调试分析本程序的基本框架比较简单,整个运行过程主要分为五个部分:主程序模块(接受链表的信息)->创建链表模块(初始化链表,即创建一个仅含头结点的空链表;按主程序模块接受的元素信息创建链表)->输出单链表模块(按一定格式输出原始链表) ->单链表逆置模块(可通过两种方式实现)->输出链表模块(按一定格式输出逆置后的链表)。
逆置单链表(基于c语言)
逆置单链表(基于c语⾔)直接插⼊全部代码:(reverseLinklist函数是逆置操作)#include <stdio.h>#include <stdlib.h>#include <assert.h>typedef int LDataType;typedef struct Linklist{LDataType data;struct Linklist *next;}Linklist,*pLinklist;pLinklist BuyNewNode(LDataType data); //动态⽣成新结点void InitLinklist(pLinklist *pL); //初始化单链表void PushBackLinklist(pLinklist *pL,LDataType data); //尾插void PushFrontLinklist(pLinklist *pL,LDataType data); //头插void PopBackLinklist(pLinklist* pL); //尾删void PopFrontLinklist(pLinklist *pL); //头删void PrintLinklist(Linklist *pL); //打印单链表pLinklist FindLinklist(pLinklist *pL,LDataType data); //查找指定元素,返回元素位置void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data); //指定位置插⼊void RemoveLinklist(pLinklist* pL,LDataType data); //删除第⼀个指定元素void RemoveAllLinklist(pLinklist *pL,LDataType data); //删除所有指定元素int IsEmptyLinklist(pLinklist pL); //判断链表是否为空void DestoryLinklist(pLinklist *pL); //销毁单链表pLinklist reverseLinklist(pLinklist *pL);int main(void){Linklist *first = NULL;InitLinklist(&first);PushBackLinklist(&first,5);PushBackLinklist(&first,4);PushBackLinklist(&first,3);PushBackLinklist(&first,2);PushBackLinklist(&first,1);PushBackLinklist(&first,0);PushFrontLinklist(&first,6);first = reverseLinklist(&first);PushFrontLinklist(&first,-1);PrintLinklist(first);}pLinklist BuyNewNode(LDataType data){pLinklist NewNode = (pLinklist)malloc(sizeof(Linklist));if (NewNode == NULL){printf("动态开辟内存空间失败\n");return NULL;}NewNode->data = data;NewNode->next = NULL;return NewNode;}void InitLinklist(pLinklist *pL){assert(pL != NULL); //初始化操作(*pL) = NULL;}void PushBackLinklist(pLinklist *pL,LDataType data){assert(pL != NULL); //尾插⼀个数据域为data的结点pLinklist NewNode = BuyNewNode(data);if(*pL == NULL){*pL = NewNode;return ;}pLinklist cur = *pL;while(cur->next){cur = cur->next;}cur->next = NewNode;}void PushFrontLinklist(pLinklist *pL,LDataType data){assert(pL != NULL); //头插⼀个数据域为data的结点pLinklist NewNode = BuyNewNode(data);if(*pL == NULL){*pL = NewNode;return ;}NewNode->next = *pL;*pL = NewNode;}int IsEmptyLinklist(pLinklist pL){return (pL == NULL); //判断⽆头单链表是否为空}void PopBackLinklist(pLinklist *pL){assert(pL != NULL); //尾删if(IsEmptyLinklist(*pL)){puts("链表为空,删除失败");return ;}pLinklist cur = *pL;pLinklist pre;if(cur->next == NULL){//只有⼀个结点*pL = NULL;free(cur);cur = NULL;return ;}while(cur->next){pre = cur;cur = cur->next;}pre->next = NULL;free(cur);cur = NULL;}void PopFrontLinklist(pLinklist *pL){assert(pL != NULL); //头删,既是删除第⼀个结点if(*pL == NULL){printf(" 链表为空,删除失败");return ;}pLinklist cur = *pL;*pL = cur->next;free(cur);cur = NULL;}pLinklist FindLinklist(pLinklist *pL,LDataType data){assert( pL != NULL); //找到第⼀个数据为data的结点pLinklist cur = *pL;while(cur){if (cur->data == data){return cur;}cur = cur->next;}return NULL;}void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data){assert(pL != NULL); //xiangp结点之前插⼊⼀个数据为data的元素 pLinklist NewNode = BuyNewNode(data);pLinklist cur = *pL;while(cur->next != p){cur = cur->next;}NewNode->next = p;cur->next = NewNode;}void RemoveLinklist(pLinklist *pL,LDataType data){assert(pL != NULL); //删除第⼀个数据域为data的结点pLinklist cur = NULL;pLinklist p = *pL;pLinklist pre = NULL;cur = FindLinklist(pL,data);if (cur == NULL){printf("未找到要删除的元素");return ;}if (*pL == cur){//位于第⼀个结点*pL = cur->next;free(cur);cur = NULL;return ;}while(p != cur){pre = p;p = p->next;}pre->next = cur->next;free(cur);cur = NULL;}void RemoveAllLinklist(pLinklist *pL,LDataType data){assert(pL != NULL); //删除每⼀个数据域都是data的结点pLinklist cur = NULL;pLinklist p = *pL;pLinklist pre = *pL;while(p){if (p->data == data && (*pL) == p){//第⼀个结点是pre = p;p = p->next;*pL = p;free(pre);pre = NULL;}else if(p->data == data){//后续结点是cur = p;p = p->next;pre->next = p;free(cur);cur = NULL;}else{//此结点不是pre = p;p = p->next;}}}void PrintLinklist(Linklist *pL){pLinklist cur = pL; //打印链表while(cur){printf("%d--->",cur->data);cur = cur->next;}printf("NULL\n");}void DestoryLinklist(pLinklist *pL){assert(pL != NULL); //摧毁链表pLinklist cur = *pL;pLinklist pre = NULL;if (*pL == NULL){printf("链表为空");return ;}if (cur->next = NULL){*pL = NULL;free(cur);cur = NULL;return ;}while(cur){pre = cur;cur = cur->next;free(pre);pre = NULL;}}pLinklist reverseLinklist(pLinklist *pL){if((*pL) == NULL || pL == NULL){return NULL;}if((*pL)->next == NULL){return *pL;}Linklist *p = *pL;Linklist *q = (*pL)->next;Linklist *r = *pL;while(q->next != NULL){r = q->next;q->next = p;p = q;q = r;r = r->next;}q->next = p;(*pL)->next = NULL;*pL = q;return *pL;}第⼀步就是判断这个单链表是否为空,因为我⽤了⼆级指针,因此要看链表为空的同时还要看pL是否指向有问题。
单链表的逆置
单链表的逆置单链表的逆置是⾯试官⾮常青睐的题,这个题可以看出⾯试者对链表和指针的操作。
⽽且问题也很好描述,⼀句话就表达出了⾃⼰的题。
----------------------------------------------------------------------------------------------⼀、算法思想:(头插法)<1>,将源链表分为链表头和链表实体。
<2>,将链表实体节点⽤头插法依次插⼊到链表头中。
<3>,如果链表实体插完则算法结束,否则转到<2>.--------------------------------------------------------------------------------------------⼆、算法的实现:头插法:void reverse(struct node *head){if (head == NULL)return ;struct node *p = head->next,*pnext = NULL;head->next = NULL;while (p != NULL) {pnext = p->next;p->next = head->next;head->next = p;p = pnext;}return ;}利⽤辅助指针void ListReverse2(LinkList L){LNode *real = L->next; //带头结点的链表,real指向第⼀个实结点//real为NULL,则链表为只含头结点的空表//real->nexxt为NULL,则链表只含有⼀个结点if(real == NULL || real->next == NULL)return;LNode *pre = real; //先前指针LNode *cur = real->next; //当前指针LNode *suc = NULL; //后继指针while(cur != NULL){suc = cur->next;cur->next = pre;pre = cur;cur = suc;}real->next = NULL; //while执⾏后第⼀个结点和第⼆个结点互指L->next = pre; //记录新的头结点}。
单链表的逆置(C++实现)
单链表的逆置(C++实现) 单链表以及逆置是什么就不说了,就简单说⼀下思想:链表的初始状态:具体的⽅法就是将头节点后⾯的节点,依次通过指针指向,插⼊head头节点之后,即可完成逆置过程. ⽰意图(这⾥我写⼀下中间处理流程,因为这样⽐较直观.第⼀次的处理与正常处理雷同):需要注意的主要有两点:1. 逆置之后的链表的尾部要NULL.在这⾥就是刚开始的时候的pHead->next->next = nullptr,具体可参考实现代码.2. 当curr指向最后⼀个节点时,需要特殊处理⼀下.实现代码:#include <iostream>using namespace std;template <typename T>struct Node{Node(T t){data = t;}T data;Node *next;};template <typename T>class List{public:List(){CreatList();}~List(){Node<T> *start = head;Node<T> *end = start->next;while (end){delete start;start = end;end = end->next;}delete start;}void CreatList(){head = new Node<T>(-100);Node<T> *temp = nullptr;rear = head;for (int i = 0; i < 10; i++){temp = new Node<T>(i);temp->next = nullptr;rear->next = temp;rear = temp;}rear->next = nullptr;}void ReverseList(){Node<T> *curr, *beh;curr = head->next;rear = head->next;beh = curr->next;while (beh){curr->next = head->next;head->next = curr;curr = beh;beh = beh->next;}curr->next = head->next;/*处理`curr`指向最后⼀个节点*/ head->next = curr;/*处理链表的尾部 nullptr */rear->next = nullptr;}void Print(){Node<T> *temp = head->next;while (temp){std::cout << temp->data << " ";temp = temp->next;}std::cout << std::endl;}private:Node<T> *head;Node<T> *rear;};int main(void){List<int> list;list.Print();list.ReverseList();list.Print();}运⾏结果:附录:顺便⽤⼀下valgrind这个内存检测⼯具我们去掉析构函数,并使⽤:valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes ./a.out其中–leak-check=full 指的是完全检查内存泄漏,–show-reachable=yes是显⽰内存泄漏的地点,–trace-children=yes是跟⼊⼦进程。
单链表逆置
单链表逆置题目:创建一个单链表并且逆置单链表完成日期:2014-09-17一、需求分析1、有一个单链表的第一个结点指针为head,编写一个函数将该单链表逆置,即最后一个结点变成第一个结点,原来倒数第二个结点变成第二个结点。
在逆置中不能建立新的单链表.2、程序执行的命令包括:(1)创建第一个单链表;(2)逆位序输入n个元素的值,建立带表头节点的单链线性表L;(3)逆置链表设置头结点由指向第一个结点改成指向最后一个结点;(4)输出销毁。
3、测试数据输入:10 9 8 7 6 5 4 3 2 1二、概要设计1、链表的抽象数据类型定义为:typedef struct LNode{int data;struct LNode* next;}LNode, *LinkList;/* 创建一个链表*/void CreateList_1(LinkList *L, int n){/*逆位序输入n个元素的值,建立带表头节点的单链线性表L*/int i;LNode* p = NULL;*L = (LinkList)malloc(sizeof(LNode));(*L)->next = NULL; /*先建立一个带头结点的单链表*/for (i = n; i > 0; --i){p = (LinkList)malloc(sizeof(LNode)); /*生成新结点*/scanf("%d", &(p->data));p->next = (*L)->next;(*L)->next = p;}}2、本程序包含五个模块:(1)主程序模块:void main(){定义头结点;创建一个链表;输出;逆置;输出;销毁;}(2)逆位序输入n个元素的值,建立带表头节点的单链线性表L(3)先建立一个带头结点的单链表在生成新结点;(4)输出链表数据,逆置链表,设置头结点由指向第一个结点改成指向最后一个结点;(5)把结点1的指针域设置为NULL,最后返回L。
单链表的逆序(反转)
单链表的逆序(反转)单链表的逆序,本来不是算法这一部分的,怎奈何小伙伴们说,面试考的机率比较大,故此就把它跟算法放到一起了。
关于单链表逆序的基本知识点,请参加:/autumn20080101/article/details/7607148 当您看了上面博文的一部分,就能基本了解的时候,下面的内容应该适合您了。
下面的内容是对单链表逆序的关键知识点的一个总结。
博主客人觉得,单链表最关键的是本节点有一个指向下一个节点的指针(即后继节点指针),双向链表则是本节点有一个前驱节点和一个后继节点。
单链表时通过while循环,从头节点开始,直到节点的后继节点为空时,则到达了链表的尾部。
其实,单链表逆序,靠的就是下面的关键代码:1 while (head != NULL) {2 //在头节点改变之前,先获取下一个节点的指针3 next = head->Next;4 //头节点的下一个节点要改成它的上一个节点,是一个逆转的过程5 head->Next = prev;6 //上一个节点前移指向头节点7 prev = head;8 //头节点前移指向下一个节点9 head = next;10 }开发环境为:qt, c语言代码:完整代码:1 #include <QCoreApplication>23 //定义常数值4 #define LEN 35 const int MAX_NUM = 5;67 //定义节点8 //typedef struct tagNode* linkNode;9 typedef struct tagNode{10 int key;11 char value[LEN];12 struct tagNode* Next;13 } *Node, *linkList;1415 //生成链表16 linkList generateLinkList();17 //释放链表18 void freeLinkList(linkList list);19 //反转链表20 Node ReverseLinkList(Node head);21 //打印链表22 void printLinkList(linkList list);2324 int main(int argc, char *argv[])25 {26 QCoreApplication a(argc, argv);27 //生成链表28 Node head = generateLinkList();29 printf("反转之前的链表\r\n");30 //打印链表31 printLinkList(head);32 //链表反向33 head = ReverseLinkList(head);34 printf("反转之后的链表\r\n");35 //打印反向后的链表36 printLinkList(head);37 //释放链表内存38 freeLinkList(head);39 return a.exec();40 }41 /**42 * @函数名:generateLinkList43 * @参数:无44 * @返回值:链表对象指针(首节点)45 * @用途:生成链表对象46 * @作者:yangfy47 */48 linkList generateLinkList()49 {50 Node head, prev;51 //头节点52 head = (Node)malloc(sizeof(Node));53 head->key = 1;54 snprintf(head->value, LEN - 1, "%c", 65);55 //prev初始指向头节点56 prev = head;57 //初始化链表元素58 for(int i = 1; i < MAX_NUM; i++){59 Node pNode = (Node)malloc(sizeof(Node));60 //形成链表数据61 pNode->key = i + 1;62 pNode->Next = NULL;63 snprintf(pNode->value, LEN - 1, "%c", 65 + i);64 //前一个节点的下一个节点指向本节点(pNode)65 prev->Next = pNode;66 //把前一个节点置为本节点,进入下一个循环67 prev = pNode;68 }69 return head;70 }71 /**72 * @函数名:freeLinkList73 * @参数:head:头节点指针74 * @返回值:无75 * @用途:链表指针内存资源的释放。
数据结构C语言版顺序表和单链表的逆置精编WORD版
数据结构C语言版顺序表和单链表的逆置精编W O R D版IBM system office room 【A0816H-A0912AAAHH-GX8Q8-GNTHHJ8】实验1-1 顺序表的逆置操作程序原码#include<stdlib.h> // 创建顺序表,确定元素个数,插入各个元素,逆置列表。
#include<stdio.h>#include<malloc.h>#define max_list_size 100 //定义给顺序表分配空间大小typedef struct{int *elem;int length;}list_node; //指向顺序表首地址的结构体单元list_node L; //这里使用了全局变量,在所有的函数里可以随意修改其值int list[max_list_size];void init(); // 初始化操作void inversion(); // 倒置部分void creat(); // 建表部分void display(); // 显示部分//*************主函数******************int main(){init();creat();printf("\n您输入的顺序表的结点数: \n");display();inversion();printf("\n倒置顺序表的结点数: \n");display();}//*************初始化操作分配空间****************** void init(){L.elem = (int *) malloc (max_list_size * sizeof(int) );if (! L.elem) {printf("顺序表已满");exit(-1);}L.length = 0;}//*************以下为建表部分******************void creat(){int a, b, i;printf("请输入顺序表的结点数: ");scanf("%d", &a);if(a<=0){printf("顺序表个数要为正整数!请重新输入: ");scanf("%d",&a);}if( a > max_list_size - 1 || a < 0 ){printf("分配失败,退出程序! \n");exit(1);}for( i = 0; i != a; ++i){printf("请输入第%d结点的值: ", i+1);scanf("%d", &b);L.elem[i] = b;++L.length;}}//****************以下为倒置部分**********************void inversion(){int a, b, i;a = L.length;for( i = 1; i <= a/2; i++){b = L.elem[i-1];L.elem[i-1] = L.elem[a-i];L.elem[a-i] = b;}}//****************以下为显示部分********************** void display(){int i;for( i = 1; i <= L.length; ++i)printf("%d\t", L.elem[i-1]);printf("\n");}实验1-1 测试结果输入一个正数、输入一个负数、实验1-2 单链表的逆置操作程序原码//创建一个单链表,确定元素个数,插入各个元素,进行逆置操作,并输出。
单链表的逆置实验报告
node *p=NULL;
node *u=NULL;
node* l=t;
while(l!=NULL)
{
u=l;
l=l->next;
u->next=p;
p=u;
}
t=p;
}
//主函数.h
#include<iostream>
#include"单链表逆置.h"
using namespace std;
void zhuhanshu(list &l)
{
cout<<"请逆序输入链表的值以0结束!"<<endl;
int a;
cin>>a;
while(a!=0)
{
node *p=new node;
p->data=a;
p->next=t->next;
t->next=p;
cin>>a;
}
}
void list::Screatlist(node* &t)//单链表的顺序构建
{
char c;
cout<<"请选择输入链表的方式顺序(S/s)逆序(N/n)"<<endl;
cin>>c;
switch(c)
{
case 'S':case 's':
l.Screatlist();break;
case 'N':case 'n':
l.Ncreatlist();break;
default:
t->next=p;
单链表逆置代码
//* * * * * * * * * * * * * * * * * * * * * * * *//*CHAPTER :2 (2_2) *//*PROGRAM :链式结构的线性表*//*CONTENT :生成,插入,删除,定位,查找*//* * * * * * * * * * * * * * * * * * * * * * * *#include <conio.h>#include <dos.h>#include <stdio.h>#include <stdlib.h>#define LEN sizeof(LNode) //定义LEN为一个节点的长度enum BOOL{False,True}; //定义BOOL型typedef struct node{char data; //数据域struct node *next;//指向下一个节点的指针}LNode,*LinkList;void CreatList(LinkList &,int); //生成一个单链表BOOL ListInsert(LinkList &,int,char); //在单链表中插入一个元素BOOL ListDelete(LinkList &,int,char &); //在单链表中删除一个元素BOOL ListFind_keyword(LinkList,char,int &); //按关键字查找一个元素BOOL ListFind_order(LinkList,char &,int); //按序号查找一个元素void ListPrint(LinkList); //显示单链表所有元素void inverse(LinkList &);void main(){LinkList L;BOOL temp;int num,loc,flag=1;char j,ch;// textbackground(3); //设置屏幕颜色//textcolor(15);// clrscr();//---------------------程序解说-----------------------printf("本程序实现链式结构的线性表的操作。
单链表逆序算法
下面来看一下很经典的“单链表逆序”问题。
很多公司的面试题库中都有这道题,有的公司明确题目要求不能使用额外的节点存储空间,有的没有明确说明,但是如果面试者使用了额外的节点存储空间做中转,会得到一个比较低的分数。
如何在不使用额外存储节点的情况下使一个单链表的所有节点逆序?我们先用迭代循环的思想来分析这个问题,链表的初始状态如图(1)所示:图(1)初始状态初始状态,prev是NULL,head指向当前的头节点A,next指向A节点的下一个节点B。
首先从A节点开始逆序,将A节点的next指针指向prev,因为prev 的当前值是NULL,所以A节点就从链表中脱离出来了,然后移动head和next 指针,使它们分别指向B节点和B的下一个节点C(因为当前的next已经指向B节点了,因此修改A节点的next指针不会导致链表丢失)。
逆向节点A之后,链表的状态如图(2)所示:图(2)经过第一次迭代后的状态从图(1)的初始状态到图(2)状态共做了四个操作,这四个操作的伪代码如下:head->next = prev;prev = head;head = next;next = head->next;这四行伪代码就是循环算法的迭代体了,现在用这个迭代体对图(2)的状态再进行一轮迭代,就得到了图(3)的状态:图(3)经过第二次迭代后的状态那么循环终止条件呢?现在对图(3)的状态再迭代一次得到图(4)的状态:图(4)经过第三次迭代后的状态此时可以看出,在图(4)的基础上再进行一次迭代就可以完成链表的逆序,因此循环迭代的终止条件就是当前的head指针是NULL。
现在来总结一下,循环的初始条件是:prev = NULL;循环迭代体是:next = head->next;head->next = prev;prev = head;head = next;循环终止条件是:head == NULL根据以上分析结果,逆序单链表的循环算法如下所示:61 LINK_NODE *ReverseLink(LINK_NODE *head)62{63 LINK_NODE *next;64 LINK_NODE *prev = NULL;6566while(head != NULL)67{68 next = head->next;69 head->next = prev;70 prev = head;71 head = next;72}7374return prev;75}现在,我们用递归的思想来分析这个问题。
c语言单链表反转
c语⾔单链表反转单链表反转可⽤迭代法,也可⽤递归⽅法,这⾥⽤迭代法(循环)实现。
⽰意图如下,其中pre指前⼀个节点,cur指当前节点,temp为临时节点。
主要思路就是让当前节点指向前⼀个节点,即cur->next=pre,需要事前将cur->next赋值给temp。
然后下移即可。
#include <stdio.h>typedef struct node_s {int item;struct node_s* next;}node_t,*link;//新建节点link newNode(int item) {link new = malloc(sizeof(node_t));new->item = item;new->next = NULL;return new;}link Reverse(link header){if (header == NULL || header->next == NULL) {return header;}link pre; //前⼀个link cur; //当前link temp;//临时变量pre = header;cur = header->next;pre->next = NULL;while (cur != NULL){temp = cur->next; //temp暂存cur->next = pre; //cur指向后⾯实现逆序pre = cur; //pre后移cur = temp; //cur后移}return pre;}void printLink(node_t* header){while (header != NULL){if (header->next != NULL){printf("%d->", header->item); //不是最后⼀个}else{printf("%d", header->item);}header = header->next;}printf("\n");}int main(int argc, char* argv[]){//创建单向链接node_t *header = NULL, *cur = NULL;for (int i = 1; i <= 3; ++i) {node_t* new = newNode(i);if (header == NULL){header = new;}else{cur->next = new; //加到后⾯}cur = new;}printLink(header); //打印链表auto newHeader = Reverse(header); //auto关键字,只⽤在赋值语句中printLink(newHeader);system("pause");}。
C语言实现单链表反转
C语⾔实现单链表反转⼀、理解指针看懂链表的结构并不是很难,但是⼀旦把它和指针混在⼀起,就很容易让⼈摸不着头脑。
所以,要想写对链表代码,⾸先就要理解好指针。
有些语⾔有“指针”的概念,⽐如 C 语⾔;有些语⾔没有指针,取⽽代之的是“引⽤”,⽐如 Java、Python。
不管是“指针”还是“引⽤”,实际上,它们的意思都是⼀样的,都是存储所指对象的内存地址。
将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量。
p->next=q。
这⾏代码是说,p 结点中的 next 指针存储了 q 结点的内存地址。
p->next=p->next->next。
这⾏代码表⽰,p 结点的 next 指针存储了 p 结点的下下⼀个结点的内存地址。
C语⾔标准规定,对于⼀个符号的定义,编译器总是从它的名字开始读取,然后按照优先级顺序依次解析。
对,从名字开始,不是从开头也不是从末尾,这是理解复杂指针的关键! 对于初学者,有⼏种运算符的优先级⾮常容易混淆,它们的优先级从⾼到低依次是:定义中被括号( )括起来的那部分。
后缀操作符:括号( )表⽰这是⼀个函数,⽅括号[ ]表⽰这是⼀个数组。
前缀操作符:星号*表⽰“指向xxx的指针”。
在本章中我们最多只⽤到⼆级指针因此将对⼆级指针做下说明。
⽐如int **p,是什么意思?⾸先看 *p 。
“*”表⽰P是⼀个指针。
但是是指向什么的指针呢?在看前⾯的int* ,int是⼀个整型类型后⾯加⼀个“*”表⽰整型类型的指针。
*p就是指向整型类型指针的指针。
p保存的是整型类型指针的地址。
⼆、警惕指针丢失和内存泄漏 不知道你有没有这样的感觉,写链表代码的时候,指针指来指去,⼀会⼉就不知道指到哪⾥了。
所以,我们在写的时候,⼀定注意不要弄丢了指针。
指针往往都是怎么弄丢的呢?我拿单链表的插⼊操作为例来给你分析⼀下。
单链表原地逆置算法
单链表原地逆置算法
单链表是一种线性数据结构,它由一系列节点组成,每个节点包含一个值和一个指向下一个节点的指针。
链表的逆置是将链表中的节点按照相反的顺序重新排列,使得原来的尾节点成为新的头节点,原来的头节点成为新的尾节点。
单链表的逆置算法可以采用原地逆置的方式实现,即不需要额外的空间来存储新的链表,而是在原链表的基础上进行修改。
算法的思想是利用三个指针来遍历链表,分别指向当前节点、前一个节点和后一个节点,将当前节点的指针指向前一个节点,然后依次向后移动指针。
具体的实现步骤如下:
1. 定义三个指针p、q、r,分别指向当前节点、前一个节点和后一个节点。
2. 将p指向链表的头节点,将q和r初始化为NULL。
3. 遍历链表,依次将p的指针指向q,将q指向p,将p指向r,然后依次向后移动指针。
4. 当p指向NULL时,说明已经遍历完整个链表,此时将头节点的指针指向q,即可完成链表的逆置。
算法的时间复杂度为O(n),空间复杂度为O(1),是一种非常高效的链表逆置方法。
下面是Python实现代码:
```python
class Node:
def __init__(self, val):
self.val = val
self.next = None
def reverseList(head: Node) -> Node:
p, q, r = head, None, None
while p:
r = p.next
p.next = q
q = p
p = r
return q
```
以上就是单链表原地逆置算法的详细介绍和Python实现代码。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
first=new Node<T>; first->next=NULL;
}
/*
*前置条件:单链表不存在
*输 入:顺序表信息的数组形式a[],单链表长度n
*功 能:将数组a[]中元素建为长度为n的单链表
*输 出:无
*后置条件:构建一个单链表
*/
template <class T>
*后置条件:单链表不变
*/
template <class T>
int LinkList<T>::Locate(T x)
{
Node<T> *p; int j;
p=first->next; j=1;
if(p&&p->next){
while(p->data!=x)
{
*后置条件:单链表不变
*/
template <class T>
T LinkList<T>::Get(int i)
{
Node<T> *p; int j;
p=first->next; j=1; //或p=first; j=0;
while (p && j<i)
{
p=p->next; //工作指针p后移
j++;
}
if (!p) throw "位置";
else return p->data;
}
/*
*前置条件:单链表存在
*输 入:查询元素值x
*功 能:按值查找值的元素并输出位置
*输 出:查询元素的位置
{
Node<T> *p;
p=first->next;
while (p)
{
cout<<p->data<<endl;
p=p->next;
}
}
template <class T>
void LinkList<T>::Reverse()
{
Node <int> *p,*u;
T Delete(int i); //在单链表中删除第i个结点
void PrintList( ); //遍历单链表,按序号依次输出各元素
void Reverse();
private:
Node<T> *first; //单链表的头指针
//LinkList.cpp
#include "LinkList.h"
/*
*前置条件:单链表不存在
*输 入:无
*功 能:构建一个单链表
*输 出:无
*后置条件:构建一个单链表
*/
template <class T>
LinkList<T>:: LinkList( )
{
s=new Node<T>; s->data=a[i]; //为每个数组元素建立一个结点
r->next=s; r=s; //插入到终端结点之后
}
r->next=NULL; //单链表建立完毕,将终端结点的指针域置空
}
/*
*前置条件:无
LinkList<T>:: LinkList(T a[ ], int n)
{
first=new Node<T>; //生成头结点
Node<T> *r,*s;
r=first; //尾指针初始化
for (int i=0; i<n; i++)
delete q;
return x;
}
}
/*
*前置条件:单链表存在
*输 入:无
*功 能:单链表遍历
*输 出:输出所有元素
*后置条件:单链表不变
*/
template <class T>
void LinkList<T>::PrintList( )
j++;
}
if (!p) throw "位置";
else {
Node<T> *s;
s=new Node<T>;
s->data=x; //向内存申请一个结点s,其数据域为x
s->next=p->next; //将结点s插入到结点p之后
void main( )
{
int b[10];
int i;
cout<<"请输入10个整数:"<<endl;
for(i=0;i<10;i++)
cin>>b[i];
LinkList <int> a(b,10);
a.Reverse();
cout<<"执行逆置操作后单链表为:"<<endl;
int Length(); //求单链表的长度
T Get(int i); //取单链表中第i个结点的元素值
int Locate(T x); //求单链表中值为x的元素序号
void Insert(int i, T x); //在单链表中第i个位置插入元素值为x的结点
};
#endif Leabharlann while(p) {
u=p->next;
p->next=first->next;
first->next=p;
p=u;
}
}
#include "iostream.h"
#include "LinkList.cpp"
a.PrintList(); //输出单链表所有元素
}
j++;
}
if (!p || !p->next) throw "位置"; //结点p不存在或结点p的后继结点不存在
else {
Node<T> *q; int x;
q=p->next; x=q->data; //暂存被删结点
p->next=q->next; //摘链
*/
template <class T>
T LinkList<T>::Delete(int i)
{
Node<T> *p; int j;
p=first ; j=0; //工作指针p初始化
while (p && j<i-1) //查找第i-1个结点
{
p=p->next;
*输 入:无
*功 能:无
*输 出:无
*后置条件:无
*/
template <class T>
LinkList<T>:: ~LinkList()
{
}
/*
*前置条件:单链表存在
*输 入:查询元素位置i
*功 能:按位查找位置为i的元素并输出值
*输 出:查询元素的值
p->next=s;
}
}
/*
*前置条件:单链表存在
*输 入:无
*功 能:输出单链表长度
*输 出:单链表长度
*后置条件:单链表不变
*/
template <class T>
int LinkList<T>::Length( )
{
Node <T> *p = first->next;
p=first->next;
first->next=NULL;//LinkList.h 声明类LinkList
#ifndef LinkList_H
#define LinkList_H
template <class T>
struct Node
{
T data;
Node<T> *next; //此处<T>也可以省略
};
template <class T>
class LinkList
{
public:
LinkList( ); //建立只有头结点的空链表
LinkList(T a[ ], int n); //建立有n个元素的单链表
~LinkList(); //析构函数
*/
template <class T>
void LinkList<T>::Insert(int i, T x)
{
Node<T> *p; int j;
p=first ; j=0; //工作指针p初始化
while (p && j<i-1)
{
p=p->next; //工作指针p后移
int i = 0;
while(p)
{
p = p->next;
i++;
}
return i;
}
/*