单链表逆置算法详解
单链表的逆置(头插法,就地逆转)
单链表的逆置(头插法,就地逆转)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;
}。
单链表逆置算法详解
/*****************************************
*Funtion: LNode*Creation(int n)
*Descrition: create a singly linked list according to the specified length
*Data:2014-02-28 ******************************/
LinkList Reverse(LNode *head)
{
LNode *p;
//定义中间转换节点
LNode *r;
if(head->next && head->next->next)
{
p=head; //获取头节点地址
printf(“%d ”,p2->num); p2=p2->num; } return 0; }
*Param: n indicate the length you want to create.
*Data:2014-02-28
*****************************************/
LNode *Creation(int n)
{
LinkList head; //定义一个头节点
r=p->next; //获取链表第二个节点地址
p->next=NULL; //头节点变尾节点之后下个指向是 NULL
while(r)
{
p=r; //第一个节点顺移
r=r->next;
//第二个节点顺移
单链表原地逆置(头插法)
程序执行结果:
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);//依次输出链表的值
编写算法:实现带头结点单链表的逆置算法
编写算法:实现带头结点单链表的逆置算法标题:探讨带头结点单链表的逆置算法实现及其应用在计算机科学和算法领域,链表是一种非常重要的数据结构,它能够以一种灵活的方式存储和组织数据。
在链表的操作中,逆置算法是一种常见且有用的操作,它能够将链表的顺序颠倒,为问题的解决提供便利。
本文将从简到繁,由浅入深地探讨带头结点单链表的逆置算法的实现及其应用。
1. 带头结点单链表的定义和特点带头结点单链表是一种特殊的链表结构,它在链表的头部增加了一个额外的结点,这个结点并不存储实际的数据,而是作为头结点来方便链表的操作。
带头结点单链表的特点是可以方便地插入和删除操作,同时也更容易处理空链表的情况。
2. 逆置算法的基本思路在带头结点单链表中,逆置算法的基本思路是从链表的第一个结点开始,依次改变每个结点的指针指向,将整个链表的方向颠倒过来。
在实现逆置算法时,需要注意处理好结点指针的指向关系,以免出现指针丢失或者内存泄露的情况。
3. 逆置算法的具体实现(1)需要判断链表是否为空或只有一个结点,如果是的话,则无需进行逆置操作。
(2)使用三个指针分别表示当前结点、前驱结点和后继结点,通过改变指针的指向来逆置链表。
(3)循环迭代链表,直到当前结点为空,完成链表的逆置操作。
4. 逆置算法的应用带头结点单链表的逆置算法在实际应用中有着广泛的使用场景,例如在字符串操作、图论算法、树算法等方面都能够发挥重要作用。
通过逆置算法,可以方便地实现字符串逆置、图的拓扑排序、二叉树镜像等复杂的数据操作。
带头结点单链表的逆置算法是一种非常重要的链表操作,它能够为问题的解决提供便利。
通过对逆置算法的深入理解和应用,可以为算法的设计和问题的解决提供更多的灵感和思路。
希望本文的内容能够帮助读者更深入地理解带头结点单链表的逆置算法,并在实际应用中发挥重要作用。
个人观点:带头结点单链表的逆置算法是一种非常有趣且实用的算法操作,它能够为链表操作和数据处理提供更多的灵活性和便利性。
单链表的逆置的实现
| t
| (3) |(4)
r y
第三个循环(并对上面的进行整理)
---------------------------------------------
(1) t = y->next
b ---> a ---> NULL c ---> d --> NULL
| | |(1)
r y t
r y t
---------------------------------------------
(2) y->next = r
b ---> a ---> NULL c ---> d --> NULL
| (2) | |(1)
y r t
---------------------------------------------
|(0) (2) | (1)
| t
|(3) | (4)
r y
第二次while循环(并对上面进行整理)
---------------------------------------------
(1) t = y->next
a ---> NULL b ---> c ---> d --> NULL
| | |(1)
单链表的逆置的实现:
(1)算法
struct link
{
int data;
struct link *next;
};
link reverse(link x)
{
if( NULL==x )
return NULL;
link t=NULL;
link r=NULL, y=x; //(0)
数据结构单链表、双链表的逆置算法
数据结构与算法的课程设计课程设计题目:数据结构的逆置算法院系名称:信息技术学院专业(班级):计算机2班姓名:学号:指导教师:实验内容:分别用一维数组,单链表,双链表实现逆置(一)使用一维数组实现逆置1.需求分析:定义一个一维数组(整型),用for语句实现循环,给数组元素赋值,并将数组元素逆序输出。
2.详细设计:main(){ int a[3],i; /*定义元素个数为3的一维数组*/for(i=0;i<3;i++)scanf("%d",&a[i]);for(i=2;i>=0;i--)printf("%d ",a[i]);getch();}3.运行及调试:4.附录:#include<stdio.h>void main(){ int a[3],i; /*定义一维数组*/for(i=0;i<3;i++)scanf("%d",&a[i]);for(i=2;i>=0;i--)printf("%d ",a[i]);getch();}(二)单链表实现逆置1.需求分析:创建一个单链表并实现逆序输出2.详细设计:定义的所有数据类型,对每个操作写出伪码算法;对主程序和其他模块也都写出伪码算法。
(1)单链表的定义typedef struct node{ int data;/*数据域为整型*/struct node* next; /*定义结点的指针域*/}LinkList;/*数据结点*/(2)头插法建立单链表Tnode *CreatList(){ Tnode *head; /*头指针*/LinkList *p;/*工作指针/int ip;head=(Tnode *)malloc(sizeof(Tnode));head->next=NULL;/*链表开始为空*/printf("please input the number:\n");scanf("%d",&ip); /*向链表中添加元素*/while(ip!=000){ p=(LinkList *)malloc(sizeof(LinkList));/*生成新结点*/ p->data=ip; /*将值赋给新生结点*/p->next=head->next;head->next=p;scanf("%d",&ip);}if(ip==000) /*当输入的数值为000时结束*/printf("\nthe ip is end!\n\n");return head;}(3)读取链表中的数据void ReadList(Tnode *head){ LinkList *p;p=head->next;while(p){ printf("%d ",p->data);p=p->next;}printf("\n");}(4)链表的倒置void ExchangeList(Tnode *head){ LinkList *r,*s;r=head->next;head->next=NULL;while(r){ s=r->next;r->next=head->next;head->next=r;r=s;}3.运行及调试5.附录:/*带头结点的链表建立*/#include<stdio.h>#include<malloc.h>#include<conio.h>typedef struct node /*结点类型定义*/{ int data; /*结点的数据域*/struct node* next; /*结点的指针域*/}LinkList;/*数据结点*/typedef struct{ int length; /**链表的长度/struct node*next; /*结点的指针域*/}Tnode; /*头结点*/Tnode *CreatList()/*头插法建立单链表*/{ Tnode *head;LinkList *p;/*工作指针*/int ip;head=(Tnode *)malloc(sizeof(Tnode));head->next=NULL; /*链表开始为空*/printf("please ip the number:\n");scanf("%d",&ip);while(ip!=000){ p=(LinkList *)malloc(sizeof(LinkList)); /*生成新结点*/ p->data=ip; /*将元素值赋给新生结点p*/p->next=head->next;head->next=p; /*head指向p结点*/scanf("%d",&ip);if(ip==000)printf("\nthe ip is end!\n\n");return head;}void ReadList(Tnode *head) /*读取链表中的数据*/{ LinkList *p;p=head->next;while(p){printf("%d ",p->data);p=p->next;}printf("\n");}void ExchangeList(Tnode *head) /*链表的倒置*/{ LinkList *r,*s;r=head->next;head->next=NULL;while(r){ s=r->next;r->next=head->next;head->next=r;r=s;}}void Readme(){ printf("press 1 to set libiao\n");printf("press 0 to exit\n");printf("-------------------------------------------------------------------------------\n"); }void main(){ Tnode *head;int choice;while(choice){ Readme();scanf("%d",&choice);switch(choice){ case 1:head=CreatList(); /*创建单链表*/printf("the number are:\n\n");ReadList(head);printf("\n");ExchangeList(head); /**逆置后的单链表/printf("the exchange number are:\n\n"); /*打印逆置后的单链表*/ReadList(head); /*读取单链表中的数据*/getch();break;}}}(三)双链表实现逆置1.需求分析:创建一个双链表并实现逆序输出2.详细设计:定义的所有数据类型,对每个操作写出伪码算法;对主程序和其他模块也都写出伪码算法。
单链表反转(4种算法实现)
单链表反转(4种算法实现)反转链表,又可以称为翻转或逆置链表,它们表达的是同一个意思。
以图 1 所示的链表为例经过反转(翻转、逆置)后,得到的新链表如图 2 所示:通过对比图 1 和图 2 中的链表不难得知,所谓反转链表,就是将链表整体“反过来”,将头变成尾、尾变成头。
那么,如何实现链表的反转呢?常用的实现方案有4 种,这里分别将它们称为迭代反转法、递归反转法、就地逆置法和头插法。
值得一提的是,递归反转法更适用于反转不带头节点的链表;其它3 种方法既能反转不带头节点的链表,也能反转带头节点的链表。
将以图1 所示,即不带头节点的链表为例,给大家详细讲解各算法的实现思想。
1、迭代反转链表该算法的实现思想非常直接,就是从当前链表的首元节点开始,一直遍历至链表的最后一个节点,这期间会逐个改变所遍历到的节点的指针域,另其指向前一个节点。
具体的实现方法也很简单,借助 3 个指针即可。
以图 1 中建立的链表为例,首先我们定义3 个指针并分别命名为beg、mid、end。
它们的初始指向如图 3 所示:在上图的基础上,遍历链表的过程就等价为:3 个指针每次各向后移动一个节点,直至mid 指向链表中最后一个节点(此时end 为NULL)。
需要注意的是,这 3 个指针每移动之前,都需要做一步操作,即改变 mid 所指节点的指针域,另其指向和 beg 相同。
1)在图 3 的基础上,我们先改变 mid 所指节点的指针域指向,另其和 beg 相同(即改为 NULL),然后再将 3 个指针整体各向后移动一个节点。
整个过程如图 4 所示:2)在图4 基础上,先改变mid 所指节点的指针域指向,另其和beg 相同(指向节点 1 ),再将 3 个指针整体各向后移动一个节点。
整个过程如图 5 所示:3)在图5 基础上,先改变mid 所指节点的指针域指向,另其和beg 相同(指向节点 2 ),再将 3 个指针整体各向后移动一个节点。
整个过程如图 6 所示:4)图 6 中,虽然 mid 指向了原链表最后一个节点,但显然整个反转的操作还差一步,即需要最后修改一次mid 所指节点的指针域指向,另其和beg相同(指向节点 3)。
单链表原地逆置算法
单链表原地逆置算法
单链表原地逆置算法是指将单链表中各节点的顺序逆置,使得原先排在前面的节点现在排在后面,原先排在后面的节点现在排在前面,但是不改变节点的值。
实现此算法需要用到指针操作,具体步骤如下:
1. 定义三个指针分别为 p, q, r,其中 p 指向单链表的头节点,q 指向 p 的下一个节点,r 指向 q 的下一个节点。
2. 将 p 的 next 指针指向 NULL,表示将头节点从链表中删除。
3. 将 q 的 next 指针指向 p,即将原先的头节点连接到 q 的
后面。
4. 将 p 指向 q,q 指向 r,r 指向 q 的下一个节点,继续进
行步骤 2 和 3 直到 r 指向 NULL。
5. 最后将原先的尾节点指向 p,完成单链表的原地逆置。
单链表原地逆置算法的时间复杂度为 O(n),空间复杂度为 O(1),是比较高效的一种算法。
- 1 -。
实验二 单链表的逆转
实验二单链表的逆转一、实验要求逆转一个单链表二、数据结构使用了单向链表,链表的节点都使用的是结构体。
三、算法描述1、定义一个结构体struct node{int data;node *next;};定义一个名为node的结构体,为了简便起见,结构体中只包含一个int型数据和指针。
定义四个函数:node *Input() //数据录入函数void Output(node *head) //数据输出函数void Delete(node *h) //节点删除函数node *Reverse(node *head) //链表逆序函数2、建立一条无序链表node *Input():使用三个指针 p1、p2、head,head指向第一个节点,p2为最后一个节点,p1为新节点。
每次操作时使p2->next=p1,p2=p1。
当输入为-1时使p2->next=0。
由此链表建立完成。
返回新建链表的头指针。
3、单链表的逆转总的思想:1)首先,使p1、p、p2依次指向head开始的前三个node,然后使p1赋给p->next,由此实现了p1和p的逆转;2)再将三个指针依次向后移一个node。
p1的下一个是p,p的下一个是p2,p2的下一个是p2->next;3)重复步骤2和3直至p2->next==nil,node* Reverse(node *head){node *p1,*p,*p2;p1=head;p=p1->next;p1->next=0; //使用3个指针,p1、p和p2。
令p1->next=0if(p->next!=0){p2=p->next; //使p1、p、p2依次指向head开始的前三个nodewhile(p2->next!=0){p->next=p1; //p->next,由此实现了p1和p的逆转p1=p;p=p2;p2=p2->next; //将三个指针依次向后移一个node}p->next=p1; //当p2->next==nil,完成单链表的逆转,只需再将最后两个节点p、p2的指针再分别指向p1、p即可p2->next=p;return p2;}else{p->next=p1;return p;}}四、测试数据输入数据产生无序链表,以-1结束1378-1链表上各结点的数据:1 3 7 8逆转后链表上各结点的数据:8 7 3 1输入四个数据,成功实现逆转。
单链表的就地逆置
单链表的就地逆置一.实验目的。
1. 握单链表的一些基本操作和具体的函数定义。
2. 能够利用单链表实现一些具体的功能。
二.实验要求。
1. 预习c语言中结构体的定义与基本操作。
2. 对单链表的每个操作用单独函数实现。
3. 编写完整的程序完成下面的实验内容,并上机运行。
三.实验内容。
构造一个单链表,实现对单链表的逆置。
四.程序实现。
/*对链表就地逆置*/#include#include//链表结构体typedef struct LNode{char data;LNode *next;}*LList;//创建链表void ListCreate(LList &L,int n,char *inputLList p;int i;L=(LNode *malloc(sizeof(LNode; L->next=NULL;for(i=n-1;i>=0;i--{p=(LNode *malloc(sizeof(LNode; p->data=input[i];p->next=L->next;L->next=p;}}//输出链表void ListOutput(LList &L{LList p;p=L->next;while(p{printf("%c ",p->data;p=p->next;}printf("\n";}//逆置bool ListInverse(LList &LLList p,q,r;p=L->next;if(!p return false;L->next=NULL;while(p{r=p->next;p->next=L->next;L->next=p;p=r;}return true;}//主程序int main({LList L;char *input;int NumOfMem;printf("首先创建单链表\n\n请输入单链表中元素个数:"; scanf("%d",&NumOfMem;getchar(;//错误处理while(NumOfMem<=0|NumOfMem>=65535printf("\n请输入合适的单链表中元素个数!\n"; scanf("%d",&NumOfMem;getchar(;}input=(char *malloc(NumOfMem*sizeof(char;printf("\n请输入单链表中的元素,按Enter键结束\n"; gets(input;//错误处理if(input[0]=='\0'{printf("空表!\n\n";return 0;}ListCreate(L,NumOfMem,input;printf("\n原链表为:\n";ListOutput(L;if(ListInverse(L{printf("逆置后\n";ListOutput(L;printf("\n";}elseprintf("空表!\n\n"; return 0;}程序截图五.实验心得。
实现单链表的就地逆置算法
实现单链表的就地逆置算法题目:有一个线性表(a1,a2,a3,....,an),采用带头节点的单链表L存储,设计一个算法将其就地逆置。
所谓“就地”指辅助空间应该为O(1)。
方法一:采用头插法先将L的头节点head的Next域置为NULL变成一个空链表,然后用p结点采用头插法插入到L中。
[java] view plaincopy1.static Node headInsert(Node head){2.if(head == null || head.next == null){3.System.out.println("逆置的单链表至少有2个结点");4.return null;5.}6.else{7.Node p = head.next;8.head.next = null;9.Node q = null;10.while(p != null){11.q = p;12.p = p.next;13.q.next = head;14.head = q;15.}16.return q;17.}18.}方法二:先将首节点的next置为NULL,用p,q指向单链表中相邻的两节点,将r指向q的下一个结点,然后同步后移。
当q=NULL时,表示指向原单链表的尾结点,将L的next域指向p即可。
[java] view plaincopy1.static Node invert(Node head){2.Node p,q,r;3.if(head == null || head.next == null){4.System.out.println("逆置的单链表至少有2个结点");5.return null;6.}7.else{8.p = head;9.q = p.next;10.while(q != null){11.r = q.next;12.q.next = p;13.p = q;14.q = r;15.}16.head.next = null;17.head = p;18.return head;19.}20.}[java] view plaincopy。
单链表逆置
单链表逆置题目:创建一个单链表并且逆置单链表完成日期: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。
算法总结之将单链表的每K个节点之间逆序
算法总结之将单链表的每K个节点之间逆序给定⼀个单链表的表头节点head,实现⼀个调整单链表的函数,是的每k个节点之间逆序,如果最后不够k个节点⼀组,则不调整最后⼏个节点思路:如果k的值⼩于2,不调整。
k<1 没有意义,k==1代表1个节点为1组进⾏逆序,原链表不变。
介绍两种⽅法:⽅法⼀利⽤栈结构1、从左到右便利链表,如果栈的⼤⼩不等于k,就将节点不断压⼊栈中2、当栈⼤⼩第⼀次到达k,凑齐了k个节点进⾏逆序。
然后弹出,并且连接。
第⼀组逆序完成后,记录新的头,同时第⼀组最后⼀个(原头)连接下⼀个节点package TT;import java.util.Stack;public class Test103 {public class Node{public int value;public Node next;public Node(int data){this.value = data;}}public Node reverseKNodes1(Node head, int k){if(k<2){return head;}Stack<Node> stack = new Stack<Node>();Node newHead = head;Node cur = head;Node pre = null;Node next = null;while(cur!=null){next = cur.next;stack.push(cur);if(stack.size()==k){pre=resign1(stack, pre, next);newHead = newHead==head ? cur : newHead;}cur = next;}return newHead;}public Node resign1(Stack<Node> stack, Node left, Node right){Node cur = stack.pop();if(left !=null){left.next=cur;}Node next=null;while(!stack.isEmpty()){next = stack.pop();cur.next=next;cur=next;}cur.next=right;return cur;}} ⽅法⼆、不需要栈结构,在原链表中直接调整⽤变量记录每⼀组开始的第⼀个节点和最后⼀个节点。
数据结构-实现一个单链表的逆置
数据结构-实现⼀个单链表的逆置1:这是⼀个经常被问到的⾯试题,也是⼀份⾮常基础的问题。
⽐如⼀个链表是这样的:1->2->3->4->5通过逆置后成为5->4->3->2->1。
最容易想到的⽅法是遍历⼀遍链表,利⽤⼀个辅助指针,存储遍历过程中当前指针指向的下⼀个元素,然后将当前节点元素的指针反转后,利⽤已经存储的指针往后⾯继续遍历。
代码如下:// ConsoleApplication15.cpp : 定义控制台应⽤程序的⼊⼝点。
//#include "stdafx.h"#include <malloc.h>#include <iostream>using namespace std;typedef struct node//定义链表结构体{int data;//节点内容node *next;//指向结构体的指针,下⼀个节点}node;node *create()//创建单链表{int i = 0;//链表中数据的个数node *head, *p, *q;//这些的本质是节点的地址int x = 0;head = NULL;q = NULL;//初始化q,q代表末节点p = NULL;while (1){printf("please input the data:");scanf_s("%d", &x);if (x == 0)break;//data为0时创建结束p = (node *)malloc(sizeof(node));//⽤于每次输⼊链表的数据p->data = x;if (++i == 1)//链表头的指针指向下⼀个节点{head = p;q = p;}else{q->next = p;//连接到链表尾端q = p;}q->next = NULL;/*尾结点的后继指针为NULL(空)*/}return head;}int length(node *head){int len = 0;node *p;p = head->next;while (p != NULL){len++;p = p->next;}return len;}void print(node *head){node *p;p = head;while (p)/*直到结点q为NULL结束循环*/{printf("%d ", p->data);/*输出结点中的值*/p = p->next;/*指向下⼀个结点*/}}node *search_node(node *head, int pos)//查找单链表pos位置的节点,返回节点的指针。
单链表的逆序(反转)
单链表的逆序(反转)单链表的逆序,本来不是算法这一部分的,怎奈何小伙伴们说,面试考的机率比较大,故此就把它跟算法放到一起了。
关于单链表逆序的基本知识点,请参加:/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 * @用途:链表指针内存资源的释放。
单链表逆序算法
下面来看一下很经典的“单链表逆序”问题。
很多公司的面试题库中都有这道题,有的公司明确题目要求不能使用额外的节点存储空间,有的没有明确说明,但是如果面试者使用了额外的节点存储空间做中转,会得到一个比较低的分数。
如何在不使用额外存储节点的情况下使一个单链表的所有节点逆序?我们先用迭代循环的思想来分析这个问题,链表的初始状态如图(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}现在,我们用递归的思想来分析这个问题。
逆置链表的算法
逆置链表的算法
逆置链表是一种常见的链表操作,其目的是将链表中的节点顺序颠倒,使得原先的最后一个节点变为第一个节点,第一个节点变为最后一个节点。
实现逆置链表的算法有多种,其中比较常见的一种是迭代法。
具体步骤如下:
1. 定义三个指针,分别指向当前节点(cur)、前一个节点(prev)和后一个节点(next)。
2. 初始化时,将当前节点指向头节点,前一个节点指向NULL。
3. 遍历链表,对于每个节点,执行如下操作:
a. 将后一个节点指针保存到next中,防止链表断开。
b. 将当前节点的next指针指向前一个节点prev。
c. 将prev指针指向当前节点cur。
d. 将cur指针指向后一个节点next。
4. 遍历结束后,将原先的头节点指向尾节点,尾节点指向NULL,逆置完成。
该算法的时间复杂度为O(n),空间复杂度为O(1)。
- 1 -。
循环单链表的逆转算法
循环单链表的逆转算法
循环单链表的逆转算法可以通过以下步骤实现:
1.定义一个指针prev,并将其初始化为NULL。
2.定义一个指针curr,用于遍历链表。
将其初始化为链表的头部。
3.进入循环,直到curr指向NULL(即链表为空):
o如果prev不为NULL,则将prev的next指针指向curr的下一个节点。
o将curr的next指针指向prev。
o将prev指向curr。
o将curr指向curr的下一个节点。
4.将链表的头部指向prev。
下面是算法的Python 实现:
python
def reverse_linked_list(head):
prev = None
curr = head
while curr is not None:
next_node = curr.next# 临时保存下一个节点
curr.next = prev # 将当前节点的下一个节点指向前一个节点
prev = curr # 将前一个节点指向当前节点
curr = next_node # 将当前节点指向下一个节点
return prev # 返回新的头节点
这个算法的时间复杂度是O(n),其中n 是链表的长度。
空间复杂度是O(1),因为只使用了几个指针来存储临时变量。
链表的逆置
链表的逆置
链表的逆置是一种常见的链表操作,它可以将链表中节点的顺序反转。
逆置链表的基本思路是将链表中的每个节点的指针指向前一个节点。
具体实现时,可以定义三个指针,分别指向当前节点、前一个节点和后一个节点,通过迭代的方式不断地将当前节点的指针指向前一个节点,直到遍历完整个链表。
逆置链表的时间复杂度为O(n),其中n为链表的长度。
逆置链表在很多算法和数据结构中都有应用,例如链表的排序、链表的合并等。
需要注意的是,在逆置链表的过程中需要注意链表头节点的变化,以及空链表和只有一个节点的特殊情况的处理。
- 1 -。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*****************************************
*Funtion: LNode*Creation(int n)
*Descrition: create a singly linked list according to the specified length
*Param: n indicate the length you want to create.
int num;
int i;
for(i=n;i>0;--i)
{
p1=(LinkList)malloc(sizeof(LNode)); //分配内存
scanf(“%d”,&num);
p1->num = nu
{
head = p1;
}
else
{
p2->next =p1;
r=p->next; //获取链表第二个节点地址
p->next=NULL; //头节点变尾节点之后下个指向是 NULL
while(r)
{
p=r; //第一个节点顺移
r=r->next;
//第二个节点顺移
p->next=head; // 使第二个节点的下一个节点指向前一个
head=p;
//给头节点赋值
R
Q
4.断开 R 和 Q 之间的链接
Head
R
Q
5.使 Q 指向 R
Head
R
6.最后的结果是:
Q
R
Q Head
根据不同的长度依次进行逆置 源码如下:
#include<stdio.h> #include<stdlib.h> Typedef struct List {
int num; struct List *next; }LNode,LinkList;
*Data:2014-02-28
*****************************************/
LNode *Creation(int n)
{
LinkList head; //定义一个头节点
LinkList p1;
//定义中间转换的节点
LinkList p2;
Head=NULL; //初始化头节点
//指定后继节点
}
p2=p1;
//节点后移
}
p2->next =NULL;
return head;
}
/******************************* *Function: LinkList Reverse(LNode *head) *Descrition: reverse the link according to head;
*Data:2014-02-28 ******************************/
LinkList Reverse(LNode *head)
{
LNode *p;
//定义中间转换节点
LNode *r;
if(head->next && head->next->next)
{
p=head; //获取头节点地址
printf(“%d ”,p2->num); p2=p2->num; } return 0; }
单链表逆置算法详解
思路:首先创建一个单链表,返回一个头节点的指针(head).该头节点不为 NULL, 其次进行单链表的逆置设置。具体设置方法见下:
1.单链表的原有示意图
Head
R
Q
2.断开 head 和 R 之间链接,使 head 指向 NULL
Head
R
Q
NULL
3.使 R 指向 head
Head
}
return head;
}
return head;
}
//the entry function int main() {
LinkList p1; LinkList p2; int num; printf(“输入你想创建的链表长度\n”); scanf(“%d”,&num); printf(“创建一个单向链表\n”); p1=Creation(num); printf(“逆置链表\n”); p2=Reverse(p1); printf(“逆置之后的链表是:”) while(p2) {