目录
实验题目:
设计并验证以下算法:判定带头节点单向链表L的数据元素是否为非递增有序。如果是非递增有序的,删除值相同的多与元素,并就地逆置删除后的链表L;如果不是非递增有序的,输出相应的提示。
1.根据键盘输入数据,用尾插法建立带头节点的单向链表L。
2输出带头结点单向链表L,删除值相同多与元素后的单向链表L,就地逆置后的电箱链表L。
题目分析:
1.要求使用尾插法建立链表
2.输入可能有序,可能无序,需要判断有无序,并给出结果
3.删除相同元素,要在原表上。
3.逆置链表,要在原表上
尾插法:
什么是尾插法?简单点说
就是,链表的最后一个元素为NULL,把这个NULL替换成新的元素,就是尾插法。
用图说就是:
NULL是链表的最后一个元素,替换就行。
删除相同:
怎么删除相同呢?
这里有一种思路是:
用两个指针,分别指向前一个,和后一个,如果前后两个相等,则删除后面的一个。
至于链表的删除操作,属于链表的基本操作,在这里就不多讲了,可以看教材或查阅资料
就地逆置链表:
这里的方法是:
从头结点开始,往下走,不停的把链表的指针逆转。
问:就地逆置链表要用几个工具指针?
答案是三个,为什么?
这是两个指针,我现在需要把第二个指向前一个,当我改变第二个指针的朝向时,它的指针就丢失了下一个节点的指向。如果我要把我的工具指针指向下一个节点,已经不可能了。
所以我们需要第三个指针来帮助我们记住下一个节点的位置。
源代码:
头文件:
#include <stdio.h> //头文件
#include <stdlib.h>
#include <malloc.h>
#include <conio.h>
#include <string.h>
#define ERROR 0
#define OK 1 //函数结果状态代码
#define EQUAL 1
#define OVERFLOW -1
typedef int Status; //Status 为函数返回值类型,其值为函数结果状态代码
struct NUBMER {
int nub;
} stu[50];
typedef struct NUBMER ElemType;
//链表中数据元素类型
struct LNODE {
ElemType data;
struct LNODE *next;
};
typedef struct LNODE LNode;
typedef struct LNODE *LinkList;//线性表的链式存储结构的定义
Status InitList_LinkList(LinkList *); //带头结点单向链表L的初始化
Status GetElem_LinkList(LinkList, int, ElemType *);//获取链表L第i个元素
int ListLength_LinkList(LinkList);//求链表 L的长度
int EqualList(ElemType, ElemType); //判断数据元素 e1、e2是否相等
int LocateElem_LinkList(LinkList, ElemType, int);//在链表L中寻找第一个与
int Less_EqualList(ElemType, ElemType);//判断数据元素 el 是否小于 e2数据元素 e符合 type 关系的元素
Status ListInsert_LinkList(LinkList, int, ElemType);//在链表L的第 i个元素前插入新元素 e
void MergeList_LinkList(LinkList, LinkList, LinkList *); //例 2.2 已知单链线性
//表 La 和 Lb 的元素按值非递减排列,归并后得到新的单链线性表 Lc,元素也按值非递减排列
Status Destroy_LinkList(LinkList *);//销毁一张链表
void printlist_LinkList(LinkList); //输出链表L
Status InitList_LinkList(LinkList *L) { //带头结点单向链表L的初始化
*L=(LNode *)malloc(sizeof(LNode));
if(!L)
exit(ERROR);
(*L)->next=NULL;
return OK;
}//InitList_LinkList
int ListLength_LinkList(LinkList L) { //求链表L的长度
int j=0;
while (L->next) {
L=L->next;
j++;
}
return j;
}//ListLength_LinkList
Status GetElem_LinkList(LinkList L, int i, ElemType *e) { //获取链表L的第i个元素
LinkList p;
int j;
p=L->next;
j=1;
while (p&&j<i) {
p=p->next;
++j;
}
if(!p||j>i)
return ERROR;
*e=p->data;
return OK;
}//GetElem_LinkList
Status ListInsert_LinkList(LinkList L, int i, ElemType e) { //在链表 L的第i个元素前插入新元素。
LinkList p, s;
int j;
p=L;
j=0;
while (p&&j<i-1) {
p=p->next;
++j;
}
if(!p||j>i-1) return ERROR;
s=(LinkList)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}//ListInsert_LinkList
Status Destroy_LinkList(LinkList *L) { //销毁一张链表
LinkList p, q;
p=*L;
q=p->next;
while (p) {
free(p);
p=q;
q=q->next;
}
return OK;
}//DestroyQueue
void printlist_LinkList(LinkList L) { //输出链表L
int i;
LinkList p;
p=L;
while (p->next) {
p=p->next;
printf("%d ", p->data.nub);
}
printf("\n");
}//printlist_LinkList
主函数:
#include "LinkList.h" //头文件
Status Reverse_LinkList(LinkList *); //逆转一张链表
Status DeleteSame_LinkList(LinkList); //删除相同元素
void JudgeOrder_LinkList(LinkList); //判断是否为非递增有序
void input(LinkList); //根据输入创建
//*****main*****
int main() {
LinkList La;
InitList_LinkList(&La); //原链表
input(La);
printf("Original LinkList: ");
printlist_LinkList(La);
JudgeOrder_LinkList(La);
printf("\nDeduplicated LinkList: ");
DeleteSame_LinkList(La);
printlist_LinkList(La);
printf("\nReverse LinkList: ");
Reverse_LinkList(&La);
printlist_LinkList(La);
}//main
void input(LinkList La){ //根据输入创建
int n;
ElemType e;
printf("How long the LinkList will you take?\n");
scanf("%d",&n);
printf("Please input some integers to fill the LinkList.\n");
for(int i = 1; i<=n; i++) {
scanf("%d",&e.nub);
ListInsert_LinkList(La, i, e);
}
}//input
void JudgeOrder_LinkList(LinkList L) { //判断是否为非递增有序
LinkList p = L->next;
while(p->next) {
if(p->data.nub < p->next->data.nub) {
printf("\nNot in order\n");
exit(0);
}
p = p->next;
}
}//JudgeOrder_LinkList
Status Reverse_LinkList(LinkList *L) { //逆转一张链表
LinkList h,p,q,r;
h = *L;
q = h->next;
if(!q->next){
return OK;
}
p = q->next;
q->next = NULL;
while(p->next) {
r = q;
q = p->next;
p->next = r;
r = p;
p = q;
q = r;
}
h->next = p;
p->next = q;
return OK;
} //Reverse_LinkList
Status DeleteSame_LinkList(LinkList L) { //删除相同元素
LinkList q, p;
q = L->next;
while(q->next) {
p = q->next;
if(q->data.nub == p->data.nub) {
q->next = p->next;
} else {
q = p;
}
}
return OK;
} //DeleteSame_LinkList
小结:
该题目还是比较基础的,如果做不出来的话,可以尝试画图来推导指针是怎么走的。
通过画图带动抽象思维。
加油,一起努力↖(^ω^)↗