问题描述
基本操作函数,单链表的就地逆置
数据结构定义
算法思想及算法设计
就地逆置:利用一个指针,依次获取单链表中的第一个元素。借助一个过渡指针,来存放原链表或者更新后的原链表下一个结点的地址,以便进行迭代。每次循环过程中,要通过过渡指针将L向后移动一个结点,同时利用头插法的原理,将当时L所指的第一个结点插入在New的首位。
实验代码
头文件
//constant.h
#pragma once
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
//LinkList.h
#include"constant.h"
typedef int Elemtype;
struct LNode {
Elemtype data;
struct LNode* next;
};
typedef struct LNode* LinkList;
Status Print(LinkList &L);
Status Value(LinkList &L, int n);
Status InitList(LinkList &L);
Status Print(LinkList& L);
LinkList Reverse(LinkList& L, LinkList& New);
Status ListInsert_L(LinkList &L,int i,int e);
Status ListDelete_L(LinkList &L,int i);
Status DestroyList_L(LinkList&L);
Status ListEmpty(LinkList &L);
main
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include"LinkList.h"
int main()
{
LinkList L, New;
L = NULL; New = NULL;
InitList(L);
int n;
printf("请问你要输入几个数字:");
scanf("%d", &n);
if (n)
{
Value(L, n);
New = Reverse(L, New);
Print(New);
}
else
printf("无法逆置");
free(L);
free(New);
return 0;
}
基本操作函数
#define _CRT_SECURE_NO_WARNINGS
#include"LinkList.h"
#include<stdlib.h>
#include<stdio.h>
Status InitList(LinkList &L)
{
L = (LinkList)malloc(sizeof(struct LNode));
L->next = NULL;
return OK;
}
Status Value(LinkList &L,int n)
{
int i,num;
LinkList p, rear;
p = NULL; rear = L;
printf("请输入您要输入的数字:");
for (i = 0; i < n; i++)
{
scanf("%d", &num);
p = (LinkList)malloc(sizeof(struct LNode));
p->data = num;
p->next = NULL;
rear->next = p;
rear = p;
}
rear->next = NULL;
printf("输入成功\n");
return OK;
}
Status ListInsert_L(LinkList &L,int i,int e)
{
LinkList p=L,q;
int j=0;
while(p&&j<i-1) { //找到插入位置在前一个指针
p=p->next;
j++;
}
if(!p||j>i-1) return -1;//i值不合法,if(!p||i<1)
q=(LinkList)malloc(sizeof(LNode));
q->data=e;
q->next=p->next;
p->next=q;
}
Status ListDelete_L(LinkList &L,int i)
{
LinkList p=L,q;
int j=0;
while(p&&j<i-1) {
p=p->next;
j++;
}
if(!p->next||j>i-1)
return -1;//i值不合法
q=p->next;
p->next=p->next->next;
free(q);
}
Status DestroyList_L(LinkList&L)
{
LinkList p=L;
if(L) {
p=L->next;
free(L);
L=p;
}
return OK;
}
Status ListEmpty(LinkList &L)
{
if(L->next)
return 1;
else
return 0;
}
Status Print(LinkList &L)
{
//L = L->next;
while (L->next)
{
printf("%d ", L->data);
L = L->next;
}
return OK;
}
LinkList Reverse(LinkList& L, LinkList& New)
{
LinkList temp;
while (L != NULL)
{
temp = L->next; //先保存链表下一位的地址,以便进行下一步的迭代
L->next = New;
New = L;
//将原链表表头的下一位变为new,再通过下一步操作将原链表的表头变为new的表头
L = temp;
}
printf("逆置成功:");
return New;
}
分析与总结
算法复杂度:在Reverse函数中,while循环执行n次,故这个算法的时间复杂度为O(n)。
优点 | 缺点 |
---|---|
代码简单,实现就地逆置,空间复杂度为O(1)。 | 原理不易理解,而且通过这种方式得到的逆置链表不含有头指针,如需进行其他操作,这必然会造成很大的不便。 |