单链表原地逆置(头插法)

原地逆置单链表(头插法)
/*
原地逆置头插法伪算法
本函数使用的是带头节点的链表
1.将p指针指向有效数据的第二个节点
2.将p指针始终插入到phead后面,第一个有效节点前面,即插入到它俩中间位置,不论第一个有效节点是否被更改,这样就可以完全逆置单链表
3.p和q指针后移,直至移动到最后一个节点,完成插入操作
p = phead->next->next;//将p指向有效数据的第二个节点,第一个节点不需要插
q = p->next;//q指向p后面的节点,防止后面的节点丢失
phead->next->next = NULL;//把第一个节点的指针域பைடு நூலகம்为空,因为逆置结束后此节点将会是最后一个节点
while(p != NULL)
return 0;
}
PNODE create_list()
{
int val;
PNODE phead,ptail,s;
phead = (PNODE)malloc(sizeof(NODE));
if(phead == NULL)
{
printf("分配失败,程序终止\n");
exit(-1);
}
ptail=phead;
{
PNODE p;
if(phead == NULL)
{
printf("链表为空,请创建链表!\n");
}
else
{
p = phead->next;
printf("依次输出链表的值为:\n");
while(p!=NULL)
{
printf("%d\t",p->data);//依次输出链表的值
p = p->next;
*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct node
{
int data;
struct node * next;
}NODE,*PNODE;
PNODE create_list();//创建单链表函数声明
void traverse_list(PNODE phead);//输出单链表函数声明
}
}
printf("\n");
}
PNODE reverse_list(PNODE phead)//头插法,第一个有效节点不需要移动
{
PNODE p=NULL,q=NULL;
//p = (PNODE)malloc(sizeof(NODE));
//q = (PNODE)malloc(sizeof(NODE));
printf("请输入每个节点的值,以-1结束\n");
scanf("%d",&val);
while(val!=-1)
{
s=(PNODE)malloc(sizeof(NODE));//新建一个节点
if(s == NULL)
{
printf("分配失败,程序终止\n");
exit(-1);
}
s->data = val;
//s->next = NULL;
ptail->next = s;//链接到节点后面
ptail = ptail->next;//使ptail永远指向最后一个节点
scanf("%d",&val);
}
ptail->next = NULL;
printf("创建成功!\n");
return phead;
}
void traverse_list(PNODE phead)
}
程序执行结果:
PNODE reverse_list(PNODE phead);//逆置单链表函数声明
int main(void)
{
PNODE phead;
phead = create_list();
traverse_list(phead);
phead = reverse_list(phead);
traverse_list(phead);
{
p->next = phead->next;
phead->next = p;//前两步将p指向的节点插入到头节点的后面
p = q;//p向后移
if(q != NULL)
{
q = q->next;//如果q不为空,q也继续后移,直到完成所有的头插操作
}
//system("PAUSE");
}
return phead;
合集下载

单链表的逆置(头插法,就地逆转)

单链表的逆置(头插法,就地逆转)

单链表的逆置(头插法,就地逆转)1.头插法,将链表中的每个元素都插到链表头部,进⾏逆转。

void reverse1(Node*head)
{//头插法逆转单链表
Node*p,*q;
p=head->next;
head->next=NULL;
while(p)
{
q=p;
p=p->next;
q->next=head->next;
head->next=q;
}
}
2.就地逆置,将链表中的指针指向改变,最后将head指向链表最后⼀个元素(逆置后的第⼀个)。

void reverse2(Node*head)
{//就地逆转法
Node *p, *s, *t;
p = head; // p开始指向头结点的
s = p->next; // s最开始是指向第⼀个节点的
while ( s->next != null ) // 没有到最后⼀个节点就继续
{
t = s->next; // ⽤t指向s后⾯的⼀个节点
s->next = p; // 把s指向的那个节点想在转换成指向它前⾯的那个节点,这个时候就实现了逆序,⽽且是就地逆序
p = s; // p向后移动到s的位置
s = t; // s向后移动到t的位置,这时候完成了第⼀步的置序,后⾯继续重复之前的动作就OK了
}
head->next = null;
head->next = s;
}。

单链表头插法代码

单链表头插法代码

单链表头插法代码单链表是一种常见的数据结构,它由多个节点组成,每个节点包括两部分:一个数据存储区和一个指向下一个节点的指针。

插入操作是单链表的基本操作之一,在插入一个节点时,可以采用两种方法:头插法和尾插法。

在本篇文章中,我们将重点讲解单链表的头插法。

头插法是指在单链表的头节点之前插入一个新节点。

这种方法需要先创建一个新节点,并将其指针指向原头节点所指向的节点。

然后再将头节点的指针指向新节点。

相当于是在链表的头部插入新节点。

下面是头插法的代码实现:```struct node {int data;struct node *next;};void insert_node(struct node **head, int value) {struct node *new_node = (struct node*)malloc(sizeof(struct node));new_node->data = value;new_node->next = *head;*head = new_node;}```在上面的代码中,我们首先定义了一个节点结构体node,其中包含一个int类型的数据成员data和一个指向下一个节点的指针成员next。

然后,我们定义一个函数insert_node,这个函数的作用是向单链表中插入新的节点。

其中,head是指向链表头节点的指针,value 是要插入的节点的值。

在insert_node函数体中,我们首先通过malloc函数动态分配内存,创建一个新节点new_node。

然后,将新节点的data成员赋值为value,将新节点的next指针指向原head指针所指向的节点,最后将head指针指向新节点new_node。

这样,新节点就插入到链表的头部了。

总结一下,头插法是单链表中比较常用的一种插入节点的方式,通过这种方法,可以很方便地在链表头部插入新节点。

在实现的过程中需要注意,在创建新节点时要手动分配内存,否则会发生内存错误。

单链表原地逆置(头插法)

单链表原地逆置(头插法)
}
程序执行结果:
p = phead->next->next;//将p指向有效数据的第二个节点,第一个节点不需要插
q = p->next;//q指向p后面的节点,防止后面的节点丢失
phead->next->next = NULL;//把第一个节点的指针域置为空,因为逆置结束后此节点将会是最后一个节点
while(p != NULL)
PNODE reverse_list(PNODE phead);//逆置单链表函数声明
int main(void)
{
PNODE phead;
phead = create_list();
traverse_list(phead);
phead = reverse_list(phead);
traverse_l
PNODE create_list()
{
int val;
PNODE phead,ptail,s;
phead = (PNODE)malloc(sizeof(NODE));
if(phead == NULL)
{
printf("分配失败,程序终止\n");
exit(-1);
}
ptail=phead;
{
PNODE p;
if(phead == NULL)
{
printf("链表为空,请创建链表!\n");
}
else
{
p = phead->next;
printf("依次输出链表的值为:\n");
while(p!=NULL)
{
printf("%d\t",p->data);//依次输出链表的值

带头结点单链表中数据就地逆置

带头结点单链表中数据就地逆置

带头结点单链表中数据就地逆置实验3 :带头结点单链表中数据就地逆置一、实验目的:1. 会定义单链表的结点类型;2. 熟悉对单链表的一些基本操作和具体的函数定义;3. 了解和掌握单链表的调用格式。

二、实验要求:1. 认真阅读和掌握实验内容所给的程序,并上机运行;2. 保存程序运行结果,并结合程序进行分析;3. 尝试自己调试修改程序并试运行。

三、实验内容:编写算法实现带头结点单链表的就地逆置,即利用原带头结点单链表的结点空间把数据元素序列逆置。

四、实验程序:#include#include#includetypedef int datatype;typedef struct snode{datatype data;struct snode*next;}slnode;sllinitiate(slnode**head);linlistsort(slnode*head);int sllinsert(slnode*head,int i,datatype x);int slldelete(slnode*head,int i,datatype x);int sllget(slnode*head,int i,datatype*x);int sllnotempty(slnode*head);linlistsurt(slnode*head);linlistinsert(slnode*head,datatype x);converse(slnode*head);main(void){datatype test[6]={64,6,7,89,12,24};slnode*head,*p;int n=6,i;sllinitiate(&head);for(i=1;i<=n;i++)sllinsert(head,i,test[i-1]);linlistsort(head);linlistinsert(head,25);converse(head);p=head->next;while(p!=NULL){printf("%d",p->data);p=p->next;}}sllinitiate(slnode**head){if((*head=(slnode*)malloc(sizeof(slnode)))==NULL)exit(1); (*head)->next=NULL;}int sllinsert(slnode*head,int i,datatype x){slnode*p,*q;int j;p=head;j=0;while(p!=NULL&&j<i-1)< p="">{p=p->next;j++;}if(j!=i-1){printf("the insert-position parameter is wrong!\n"); return 0;}if((q=(slnode*)malloc(sizeof(slnode)))==NULL)exit(1);q->data=x;q->next=p->next;p->next=q;return 1;}int slldelete(slnode*head,int i,datatype x){slnode*p,*q;int j;p=head;j=0;while(p->next!=NULL&&j<i-1)< p="">{p=p->next;j++;}if(j!=i-1){printf("the delete-position parameter is wrong!\n"); return 0;}q=p->next;p->next=p->next->next;x=q->data;free(q);}int sllget(slnode*head,int i,datatype*x){slnode*p;int j;p=head;j=0;while(p->next!=NULL&&j<i)< p="">{p=p->next;j++;}if(j!=i){printf("the get-position parameter is wrong!\n"); return 0; }*x=p->data;return 1;}int sllnotempty(slnode*head){if(head->next==NULL)return 0;else return 1;}linlistsort(slnode*head){slnode*curr,*pre,*p,*q;head->next=NULL;while(p!=NULL){curr=head->next;while(curr!=NULL&&curr->data<=p->data){pre=curr;curr=curr->next;}q=p;p=p->next;q->next=pre->next;pre->next=q;}}linlistinsert(slnode*head,datatype x){slnode*curr,*pre,*q;curr=head->next;pre=head;while(curr!=NULL&&curr->data<=x){pre=curr;curr=curr->next;}if((q=(slnode*)malloc(sizeof(slnode)))==NULL)exit(1); q->data=x;q->next=pre->next;}converse(slnode*head) {slnode*p,*q;p=head->next;head->next=NULL; while(p!=NULL){q=p;p=p->next;q->next=head->next; head->next=q;}}</i)<></i-1)<></i-1)<>。

单链表逆序

单链表逆序

单链表逆序1. 什么是单链表?单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。

每个节点只能访问其后继节点,而无法直接访问前驱节点。

2. 单链表的逆序操作单链表的逆序操作是将链表中的节点按照相反的顺序重新排列。

例如,原始链表为1 -> 2 -> 3 -> 4 -> null,逆序后的链表为4 -> 3 -> 2 -> 1 -> null。

3. 实现方法方法一:迭代法迭代法是一种常见且简单的实现方式。

具体步骤如下:1.初始化三个指针:prev指向null,curr指向头节点,next指向curr的后继节点。

2.循环遍历整个链表:–将curr的next指针指向prev。

–将prev指针移到curr位置。

–将curr指针移到next位置。

–将next指针移到curr的后继位置。

3.遍历结束后,将头节点更新为prev。

代码示例:def reverseLinkedList(head):prev = Nonecurr = headwhile curr:next = curr.nextcurr.next = prevprev = currcurr = nexthead = prevreturn head方法二:递归法递归法是另一种常见的实现方式,它通过递归调用函数来实现链表的逆序。

具体步骤如下:1.终止条件:当链表为空或只有一个节点时,直接返回该节点。

2.递归调用:将链表的头节点的后继节点传入函数进行逆序操作。

3.将链表头节点的后继节点的next指针指向头节点,并将头节点的next指针置为null。

代码示例:def reverseLinkedList(head):if head is None or head.next is None:return headreversedHead = reverseLinkedList(head.next)head.next.next = headhead.next = Nonereturn reversedHead4. 示例假设原始链表为1 -> 2 -> 3 -> 4 -> null,我们使用上述两种方法对其进行逆序操作。

编写算法:实现带头结点单链表的逆置算法

编写算法:实现带头结点单链表的逆置算法

编写算法:实现带头结点单链表的逆置算法标题:探讨带头结点单链表的逆置算法实现及其应用在计算机科学和算法领域,链表是一种非常重要的数据结构,它能够以一种灵活的方式存储和组织数据。

在链表的操作中,逆置算法是一种常见且有用的操作,它能够将链表的顺序颠倒,为问题的解决提供便利。

本文将从简到繁,由浅入深地探讨带头结点单链表的逆置算法的实现及其应用。

1. 带头结点单链表的定义和特点带头结点单链表是一种特殊的链表结构,它在链表的头部增加了一个额外的结点,这个结点并不存储实际的数据,而是作为头结点来方便链表的操作。

带头结点单链表的特点是可以方便地插入和删除操作,同时也更容易处理空链表的情况。

2. 逆置算法的基本思路在带头结点单链表中,逆置算法的基本思路是从链表的第一个结点开始,依次改变每个结点的指针指向,将整个链表的方向颠倒过来。

在实现逆置算法时,需要注意处理好结点指针的指向关系,以免出现指针丢失或者内存泄露的情况。

3. 逆置算法的具体实现(1)需要判断链表是否为空或只有一个结点,如果是的话,则无需进行逆置操作。

(2)使用三个指针分别表示当前结点、前驱结点和后继结点,通过改变指针的指向来逆置链表。

(3)循环迭代链表,直到当前结点为空,完成链表的逆置操作。

4. 逆置算法的应用带头结点单链表的逆置算法在实际应用中有着广泛的使用场景,例如在字符串操作、图论算法、树算法等方面都能够发挥重要作用。

通过逆置算法,可以方便地实现字符串逆置、图的拓扑排序、二叉树镜像等复杂的数据操作。

带头结点单链表的逆置算法是一种非常重要的链表操作,它能够为问题的解决提供便利。

通过对逆置算法的深入理解和应用,可以为算法的设计和问题的解决提供更多的灵感和思路。

希望本文的内容能够帮助读者更深入地理解带头结点单链表的逆置算法,并在实际应用中发挥重要作用。

个人观点:带头结点单链表的逆置算法是一种非常有趣且实用的算法操作,它能够为链表操作和数据处理提供更多的灵活性和便利性。

单链表原地逆置算法

单链表原地逆置算法单链表是一种常见的数据结构,其操作包括插入、删除和查找等。

在实际应用中,有时需要将单链表进行逆置操作。

逆置操作的实现方式有多种,其中一种是原地逆置。

原地逆置是指在不使用额外空间的情况下,将单链表逆置。

具体实现方式如下: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)。

在实际应用中,可以使用该算法实现链表的逆置操作。

单链表的逆序

单链表的逆序【实用版】目录1.单链表的逆序概念2.单链表逆序的实现方法3.单链表逆序的算法复杂度4.单链表逆序的应用实例正文一、单链表的逆序概念单链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和指向下一个节点的指针。

单链表的逆序,顾名思义,就是将单链表中的节点顺序颠倒。

例如,原链表的节点顺序为 1->2->3->4,逆序后变为 4->3->2->1。

二、单链表逆序的实现方法实现单链表逆序的方法有很多,其中较为常见的是采用迭代法和递归法。

1.迭代法迭代法是通过一个循环来完成链表的逆序。

具体步骤如下:(1) 定义一个指针 pre,初始指向头节点,指向当前节点的前一个节点;(2) 定义一个指针 p,初始指向头节点;(3) 当 pre 不为空时,执行以下操作:a.将 p 指向的节点的 next 指针指向 pre;b.pre 指向 p;c.将 p 向后移动一个节点;(4) 循环结束后,p 指向的节点即为逆序后链表的头节点。

2.递归法递归法的思想是将链表不断拆分成子链表,然后对子链表进行逆序,最后将各子链表拼接起来。

具体实现如下:(1) 定义一个函数 reverse_list,接收一个链表节点作为参数;(2) 在函数中,判断传入的节点是否为空,如果为空,则返回空;(3) 将传入的节点的 next 指针指向的节点作为新的头节点,原节点的 next 指针指向 reverse_list(新头节点);(4) 返回新头节点;(5) 在主函数中,调用 reverse_list(头节点),返回的结果即为逆序后的链表。

三、单链表逆序的算法复杂度采用迭代法实现单链表逆序的时间复杂度为 O(n),其中 n 为链表的长度。

采用递归法实现单链表逆序的时间复杂度也为 O(n),但由于存在函数调用的开销,空间复杂度为 O(n)。

四、单链表逆序的应用实例单链表逆序在实际编程中应用广泛,例如在排序算法中,对链表进行逆序操作后,可以方便地进行快速排序等操作。

单链表逆置原理

单链表逆置原理
单链表逆置原理是通过改变链表中节点的指向,将链表中的节点重新排列,使得原来链表的顺序颠倒过来。

具体实现方法是使用三个指针,一个指向当前节点,一个指向上一个节点,一个指向下一个节点。

通过交换当前节点的下一个节点和上一个节点的下一个节点,实现节点的逆置。

在每一轮循环中,用p3记录p2的next位置,将p2的next指向p1,最后让p1指向p2,p2指向p3。

整个循环结束以后,p2停留在原来链表尾部的NULL处,p1停留在原来链表的最后一个元素。

其特点包括:
1.改变原链表的顺序:通过逆置操作,可以将单链表的顺序完全颠倒,变
为反向的顺序。

2.操作简单:相对于其他数据结构,单链表的逆置操作相对简单,只需要
遍历链表并交换相邻节点的指向即可。

3.对原链表无影响:逆置操作不会改变原链表中节点的值,只是改变了它
们的指向,因此不会对原链表造成任何影响。

4.适用于需要反向存储的数据结构:单链表的逆置操作可以用于需要反向
存储的数据结构,如某些算法或数据压缩等应用中。

需要注意的是,单链表的逆置操作需要小心处理边界条件和错误情况,例如链表为空或只有一个节点等情况。

同时,在逆置操作过程中需要注意内存管理,避免出现内存泄漏等问题。

链表逆序的三种方法

链表逆序的三种方法链表是一种常用的数据结构,由一个个节点通过指针连接而成。

在实际编程中,经常需要对链表进行逆序操作,以满足特定需求。

本文将介绍链表逆序的三种常用方法,分别是迭代法、递归法以及使用栈的方法。

迭代法:迭代法是一种比较直观的逆序方法,通过调整节点之间的指针指向来实现。

具体步骤如下:1. 定义三个指针,分别为当前节点(cur)、前一个节点(prev)和下一个节点(next)。

2. 将当前节点的下一个节点保存到next指针中,以免链表断开。

3. 将当前节点的next指针指向前一个节点,完成逆序操作。

4. 将当前节点赋值给prev指针,以备下一次迭代使用。

5. 将next指针赋值给cur指针,继续下一次迭代。

若next指针为空,则说明已到达链表尾部,逆序完成。

递归法:递归法是一种更为简洁的逆序方法,通过递归调用实现链表逆序。

具体步骤如下:1. 首先判断链表是否为空或只有一个节点,若是则无需逆序,直接返回。

2. 若链表有多个节点,则递归调用逆序函数对除第一个节点外的子链表进行逆序。

3. 将头节点(首节点)的指针指向调用逆序函数后的新链表的尾节点。

4. 将尾节点的指针指向头节点,使得整个链表逆序完成。

使用栈的方法:栈是一种后进先出(LIFO)的数据结构,可以利用栈的特性进行链表逆序操作。

具体步骤如下:1. 遍历链表,将链表中的节点依次压入栈中。

2. 弹出栈中的节点,按照出栈顺序重新构建链表。

弹出的第一个节点是原链表的尾节点,成为逆序链表的头节点。

3. 将每个弹出的节点的next指针指向下一个被弹出的节点,完成逆序操作。

4. 最后一个被弹出的节点成为逆序链表的尾节点,将其next指针置为空,表示逆序链表的尾部。

以上是三种常见的链表逆序方法。

在实际应用中,可以根据具体情况选择合适的方法来实现链表逆序。

迭代法适合逆序链表并保持链表结构的情况;递归法适用于逆序链表不要求保持原结构的情况;使用栈的方法适用于逆序链表并重新构建链表结构的情况。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档