代码详细解析:
版本更新日志
V1.0 : 顺序存储和链式存储, 初步利用算法库进行实现
目录
[一 . 合并顺序存储有序表](#一 . 合并顺序存储有序表)
[二 . 合并链式存储有序表](#二 . 合并链式存储有序表)
V1.0
一 . 合并顺序存储有序表
合并功能函数:
cpp
/**************************************************
函数名: Merged_ordered_list
功 能: 合并数组顺序表
参 数: SqList *LA,SqList *LB,SqList *&LC:把LA和LB合并成LC
注 意: ① 记得给LC长度赋值, 避免遍历时溢出
返回值: 无
**************************************************/
void Merged_ordered_list(SqList *LA, SqList *LB, SqList *&LC)
{
int locationA = 0;
int locationB = 0;
int locationC = 0;
LC = (SqList*)malloc(sizeof(SqList));
//LA和LB均未达到末尾,选择小的加入
while(locationA < LA->length && locationB < LB->length)
{
if(LA->data[locationA] < LB->data[locationB])
{
LC->data[locationC] = LA->data[locationA];
locationA++;
locationC++;
}
else
{
LC->data[locationC] = LB->data[locationB];
locationB++;
locationC++;
}
}
//下面多两种情况其一或者没有
//经过上一轮循环插入,LB已经扫描插入完了,
//LA尚未扫描插入完,将LA其余元素插入到Lc中
while(locationA < LA->length)
{
LC->data[locationC] = LA->data[locationA];
locationA++;
locationC++;
}
//经过上一轮循环插入,LA已经扫描插入完了,
//LB尚未扫描插入完,将LB其余元素插入到LC中
while(locationB < LB->length)
{
LC->data[locationC] = LB->data[locationB];
locationB++;
locationC++;
}
LC->length = locationC; // ①
}
用到的算法库:
list.h
cpp
#ifndef LIST_H_INCLUDE
#define LIST_H_INCLUDE
#include <malloc.h>
#define MaxSize 100
typedef int ElemType; //自定义类型
typedef struct //自定义结构体
{
ElemType data[MaxSize];
int length;
}SqList;
//①用数组创建线性表
void CreateList(SqList *&L, ElemType a[],int n);
//②初始化线性表
void InitList(SqList *&L);
//③输出线性表
void DispalyList(SqList *L);
//④判断是否为空表
bool ListEmpty(SqList *L);
//⑤销毁线性表
void DestroyList(SqList *&L);
//⑥ 求线性表的长度
int ListLength(SqList *L);
//⑦求某个位置的数据元素值GetElem(L,i,e)
bool GetElem(SqList *L,int i, ElemType &e);
//⑧ 元素 e 在 L中的序号(逻辑序号 1~n)
int LocateElement(ElemType element, SqList *L);
//⑨ L中 第 i 位, 插入 e, ListInsert(L,i,e)
bool ListInsert(SqList *&L,int i, ElemType e);
//⑩ 删除 L 中特定位置 i 的元素 e, ListDelete(L,i,e)
bool ListDelete(SqList *&L, int i, ElemType &e);
#endif
list.cpp
cpp
#include <stdio.h>
#include "list.h"
/**************************************************
①函数名: CreateList
功 能: 用数组构建顺序表
参 数: ①SqList *&L:传入的线性表 ②ElemType a[]:使用的数组
③int n: 线性表的长度(n < Maxsize)
返回值: 无
**************************************************/
void CreateList(SqList *&L, ElemType a[],int n)
{
int i;
//分配空间
L = (SqList*)malloc(sizeof(SqList));
for(i = 0; i<n; i++)
{
L->data[i] = a[i];
}
L->length = n;
}
/**************************************************
②函数名: InitList
功 能: 初始化线性表,重新分配空间,长度清成零
参 数: ①SqList *&L:要进行初始化的线性表
返回值: 无
**************************************************/
void InitList(SqList *&L)
{
L = (SqList*)malloc(sizeof(SqList)); //既然初始化了,直接重新分配空间
L->length = 0;
}
/**************************************************
③函数名: DispalyList
功 能: 输出数组线性表到控制台
使用场景: 调试输出专用
参 数: ①SqList *L:所需展示的顺序表
返回值: void
**************************************************/
void DispalyList(SqList *L)
{
if(L->length == 0) return;
for(int i = 0; i< L->length; i++)
{
printf("%d ",L->data[i]);
}
printf("\n");
}
/**************************************************
④函数名: ListEmpty
功 能: 判断顺序表是否为空
参 数: ① SqList *L: 需要判断的顺序表
返回值: (bool类型) 是空表 ? 返回1 : 不是返回0
**************************************************/
bool ListEmpty(SqList *L)
{
return(L->length == 0);
}
/**************************************************
⑤函数名 : DestroyList
功 能: 释放顺序表空间
参 数: ① SqList *&L: 所需释放的线性表的指针地址
注 意: (1)
返回值: 无
**************************************************/
void DestroyList(SqList *&L) //(1)注意是指针地址
{
//c语言, 直接free
free(L);
}
/**************************************************
⑥函数名:ListLength
功 能: 返回顺序表长度
参 数: ① SqList *L:传入顺序表的名字
返回值: int: 线性表长度值
**************************************************/
int ListLength(SqList *L)
{
return (L->length);
}
/**************************************************
⑦函数名:GetElem
功 能: 取线性表数组内,某个序号的元素值,并返回
参 数: ①SqList *L: 要取的线性表 ②int i:要取的序号(逻辑需要 1-n)
③ElemType &e:返回到特定位置
注意:①合法性判断 ② 需要把逻辑(1~n)变成物理序号(0~n-1)
返回值: bool:是否获取成功
**************************************************/
bool GetElem(SqList *L,int i, ElemType &e)
{
if(i<1 || i>L->length)//①
{
return false;
}
e = L->data[i-1]; //②
return true;
}
/**************************************************
⑧函数名: LocateElement
功 能: 查找特定元素值,在线性表中的位置(1~n)
参 数: ①ElemType element: 特定元素值 ② SqList *L:被查的线性表
返回值: int: 位置信息 (0没找到, 1~n, 即为位置)
**************************************************/
int LocateElement(ElemType element, SqList *L)
{
int i = 0;
while(i < L->length && L->data[i] != element) i++;
//如果 i跳出后, i范围超过 L->length,则 没找到
if(i >= L->length) return 0;
else return i+1;
}
/**************************************************
函数名: ListInsert
功 能: 把 e 插到到线性表 L 的第 i(逻辑序号) 个位置
参 数: (1)SqList *&L: 线性表L (2)int i: 插入到的逻辑位置
(3) ElemType e:要插入的元素值
注意:① 可插入的位置逻辑序号为1~L->length+1
②得出 j最后是等于 i+1, 所以j的范围是 j>i
③从 j=L->length得出 , data[j] = data[j-1],从而确定整体范围
返回值: bool:是否插入完成
**************************************************/
bool ListInsert(SqList *&L,int i, ElemType e)
{
int j;
if(i<1 || i>L->length+1) //①
return false;
i--; //将顺序表的逻辑序号转化为物理序号
for(j = L->length; j > i; j--) //② data[i+1] = data[i] => j = i+1
{
//③ data[i]~data[L->length-1]整体后移到data[i+1]~data[L->length]
L->data[j] = L->data[j-1];
}
L->data[i] = e; //插入元素e
L->length++; //顺序表插入增1
return true; //成功插入返回true
}
/**************************************************
函数名: ListDelete
功 能: 删除顺序表特定位置的元素
参 数: (1)SqList *&L:被删的顺序表 (2)int i:位置
(3)ElemType &e:删掉的值
注 意: ① 思路是整体前移,所以确定初始值i,然后定公式,看临界定 范围
② 最后一个是 data[L->length-2] = data[L->length-1],
得出 j = L->length-2
返回值: bool:是否删除成功? true : false
**************************************************/
bool ListDelete(SqList *&L, int i, ElemType &e)
{
int j;
if(i < 1 || i > L->length) return false;
i--; //把逻辑序号转为物理序号
e = L->data[i]; //将要删除的元素存储
for(j = i;j < L->length-1; j++)//①将data[i...n-1]整体前移
{
//② data[i+1]~data[L->length-1] => data[i] ~ data[L->length-2]
L->data[j] = L->data[j+1];
}
L->length--; //顺序表长度减去1
return true;
}
main.cpp测试函数
cpp
#include "list.h"
#include "stdio.h"
/**************************************************
函数名: Merged_ordered_list
功 能: 合并数组顺序表
参 数: SqList *LA,SqList *LB,SqList *&LC:把LA和LB合并成LC
注 意: ① 记得给LC长度赋值, 避免遍历时溢出
返回值: 无
**************************************************/
void Merged_ordered_list(SqList *LA, SqList *LB, SqList *&LC)
{
int locationA = 0;
int locationB = 0;
int locationC = 0;
LC = (SqList*)malloc(sizeof(SqList));
//LA和LB均未达到末尾,选择小的加入
while(locationA < LA->length && locationB < LB->length)
{
if(LA->data[locationA] < LB->data[locationB])
{
LC->data[locationC] = LA->data[locationA];
locationA++;
locationC++;
}
else
{
LC->data[locationC] = LB->data[locationB];
locationB++;
locationC++;
}
}
//下面多两种情况其一或者没有
//经过上一轮循环插入,LB已经扫描插入完了,
//LA尚未扫描插入完,将LA其余元素插入到Lc中
while(locationA < LA->length)
{
LC->data[locationC] = LA->data[locationA];
locationA++;
locationC++;
}
//经过上一轮循环插入,LA已经扫描插入完了,
//LB尚未扫描插入完,将LB其余元素插入到LC中
while(locationB < LB->length)
{
LC->data[locationC] = LB->data[locationB];
locationB++;
locationC++;
}
LC->length = locationC; // ①
}
int main()
{
SqList *LA,*LB,*LC;
ElemType A[3] = {1,3,5};
ElemType B[4] = {2,4,8,10};
CreateList(LA,A,3);
printf("A展示:\n");
DispalyList(LA);
CreateList(LB,B,4);
printf("B展示:\n");
DispalyList(LB);
printf("A+B合并排序成C展示:\n");
Merged_ordered_list(LA,LB,LC);
DispalyList(LC);
return 0;
}
运行演示结果:
二 . 合并链式存储有序表
合并功能函数:
cpp
/**************************************************
函数名: Union_order_singlelist
功 能: 合并两个有序单链表为一个有序单链表
参 数: LinkList *LA,LinkList *LB, LinkList *&LC:LA和LB合并为LC
注 意: ①②③结束条件, 是遍历节点为空
返回值: 无
**************************************************/
void Union_order_singlelist(LinkList *LA,LinkList *LB, LinkList *&LC)
{
// int counter = 0;
//定义遍历LA和LB的指针
LinkList *visit_A = LA->next;
LinkList *visit_B = LB->next;
//定位LC尾指针
LinkList *tail_C;
LinkList *newNode;
//为LC头结点分配空间
LC = (LinkList*)malloc(sizeof(LinkList));
tail_C = LC;
LC->next = NULL;
//轮询遍历LA和LB,数据插入LC
while(visit_A != NULL && visit_B != NULL) //①
{
//为LC新节点分配空间
newNode = (LinkList*)malloc(sizeof(LinkList));
if(visit_A->data < visit_B->data)
{
newNode->data = visit_A->data;
//处理完后,后移,为后面做准备
visit_A = visit_A->next;
//对LC进行尾插法
tail_C->next = newNode;
tail_C = newNode; //涉及指针覆盖,顺序不可调换
// counter++;
// printf("\n第%d个数是 %d \n",counter,newNode->data);
}
else
{
newNode->data = visit_B->data;
//处理完后,后移,为后面做准备
visit_B = visit_B->next;
//对LC进行尾插法
tail_C->next = newNode;
tail_C = newNode;//涉及指针覆盖,顺序不可调换
// counter++;
// printf("\n第%d个数是 %d \n",counter,newNode->data);
}
}
//经过上一步的交替插入,要么两个表交替插入完了,要么是下面两者之一
//LB已经扫描插入完了, LA尚未扫描插入完 , 将其余元素插入到 Lc中
while(visit_A != NULL)//③
{
//为LC新节点分配空间
newNode = (LinkList*)malloc(sizeof(LinkList));
newNode->data = visit_A->data;
//处理完后,后移,为后面做准备
visit_A = visit_A->next;
//对LC进行尾插法
tail_C->next = newNode;
tail_C = newNode; //涉及指针覆盖,顺序不可调换
// counter++;
// printf("\n第%d个数是 %d \n",counter,newNode->data);
}
while(visit_B != NULL) //③
{
//为LC新节点分配空间
newNode = (LinkList*)malloc(sizeof(LinkList));
newNode->data = visit_B->data;
//处理完后,后移,为后面做准备
visit_B = visit_B->next;
//对LC进行尾插法
tail_C->next = newNode;
tail_C = newNode;//涉及指针覆盖,顺序不可调换
// counter++;
// printf("\n第%d个数是 %d \n",counter,newNode->data);
}
//尾结点置空,善后工作
tail_C->next = NULL;
}
用到的算法库:
singlelist.h
cpp
#ifndef SINGLELIST_H_INCLUDE
#define SINGLELIST_H_INCLUDE
#include <stdio.h>
#include <malloc.h>
typedef int ElemType; //定义单链表节点类型
typedef struct LNode
{
ElemType data;
struct LNode *next; //指向后继节点
}LinkList;
//①头插法建立单链表
void CreatList_Head(LinkList *&L, ElemType Array_used[], int Array_number);
//②尾插法建立单链表
void CreatList_Tail(LinkList *&L, ElemType Array_used[], int Array_number);
//③输出单链表
void DisplayLinkList(LinkList *L);
//④销毁单链表
void DestroyLinkList(LinkList *&L);
//⑤ 初始化线性表
void InitLinkList(LinkList *&L);
//⑥ 判断线性表是否为空表
bool LinkListEmpty(LinkList *L);
//⑦ 返回单链表L中数据节点的个数
int LinkListLength(LinkList *L);
//⑧ 求线性表L中指定位置的某个数据元素
bool SpecificLocate_Value(LinkList *L,int location, ElemType &value);
//⑨ 按元素值查找特定元素的位置
int SpecificValue_Location(LinkList *L, ElemType value);
//⑩ 把元素插入到特定位置
bool LinkList_InsertElement(LinkList *&L, int location, ElemType &value);
//(11) 删除特定位置的节点元素
bool LinkList_Delete_Location(LinkList *&L,int location, ElemType &value);
//(12)单链表删除其中其最大节点元素
bool DeleteMaxNode(LinkList *&L);
//(13)对单链表中元素进行排序(至少有2个数据节点)
bool LinkList_sorting(LinkList *&L);
#endif // SINGLELIST_H_INCLUDE
singlelist.cpp
cpp
#include "singlelist.h"
/**************************************************
①函数名: CreatList_Head
功 能: 头插法建立单链表
参 数: (1)LinkList *&L: 传入的单链表指针地址
(2)ElemType Array_used[]:要用来建表的数组
(3)int Array_number: 数组的长度
返回值: 无
**************************************************/
void CreatList_Head(LinkList *&L, ElemType Array_used[], int Array_number)
{
int counter;
LinkList *newnode;
L = (LinkList *)malloc(sizeof(LinkList)); //创建头结点
L->next = NULL;
for(counter = 0; counter < Array_number; counter++)
{
newnode = (LinkList *)malloc(sizeof(LinkList)); //创建新节点
newnode->data = Array_used[counter];
newnode->next = L->next; //将newnode插在原开始结点之前,头结点之后
L->next = newnode;
}
}
/**************************************************
②函数名: CreatList_Tail
功 能: 尾插法建立单链表
参 数: (1)LinkList *&L: 传入的单链表指针地址
(2)ElemType Array_used[]:要用来建表的数组
(3)int Array_number:数组的长度
返回值: 无
**************************************************/
void CreatList_Tail(LinkList *&L, ElemType Array_used[], int Array_number)
{
int counter;
LinkList *newnode,*tailnode;
L = (LinkList *)malloc(sizeof(LinkList));//创建头结点
L->next = NULL;
tailnode = L; //尾结点tailnode始终指向终端结点,开始指向头结点
for(counter = 0; counter < Array_number; counter++)
{
newnode = (LinkList *)malloc(sizeof(LinkList)); //创建新节点
newnode->data = Array_used[counter];
tailnode->next = newnode; //将新节点插入到尾结点之后
tailnode = newnode; //更新尾结点
}
tailnode->next = NULL; //终端结点next域置空
}
/**************************************************
③函数名: DisplayLinkList
功 能: 输出单链表
参 数: (1)LinkList *L:将要输出的单链表
返回值: 无
**************************************************/
void DisplayLinkList(LinkList *L)
{
LinkList *shownode;
shownode = L->next;
while(shownode != NULL)
{
printf("%d",shownode->data);
printf(" ");
shownode = shownode->next; //一直遍历,直到指向尾->newt = NULL
}
printf("\n");
}
/**************************************************
④函数名: DestroyLinkList
功 能: 销毁单链表
参 数: (1)LinkList *&L:要销毁的单链表
注意:① 等到指引下一个节点的指针为Null时就跳出,避免出现野指针,此时再销毁destroyNode
② 避免断开联系,记录 销毁节点的下一个节点
返回值: 无
**************************************************/
void DestroyLinkList(LinkList *&L)
{
LinkList *destoryNode,*nextNode;
destoryNode = L;
nextNode = destoryNode->next;
while(nextNode != NULL) //①
{
free(destoryNode);
destoryNode = nextNode;
nextNode = destoryNode->next; //②
}
free(destoryNode);
}
/**************************************************
⑤函数名: InitLinkList
功 能: 初始化单链表
参 数: LinkList *&L:要被初始化的链表指针地址
返回值: 无
**************************************************/
void InitLinkList(LinkList *&L)
{
L = (LinkList *)malloc(sizeof(LinkList));//创建头结点
L->next = NULL;
}
/**************************************************
⑥函数名: LinkListEmpty
功 能: 判断单链表是否为空
参 数: (1)LinkList *L:要判断的单链表
返回值: bool: 是否为空? treu:false
**************************************************/
bool LinkListEmpty(LinkList *L)
{
return (L->next == NULL);
}
/**************************************************
⑦函数名: LinkListLength
功 能: 返回单链表L中数据节点的个数
参 数: LinkList *L:要计算的数据节点
返回值: int: 线性表数据节点个数值
**************************************************/
int LinkListLength(LinkList *L)
{
int counter = 0;
LinkList *nowNode = L;
while(nowNode->next != NULL)
{
counter++;
nowNode = nowNode->next;
}
return counter;
}
/**************************************************
⑧函数名: GetLocateValue
功 能: 求特定位置的数据元素值
参 数: (1)LinkList *L:要找的单链表
(2)int location:所要找的位置
(3)ElemType &value: 传递回所要找的值
注意: ① 判断跳出的时候, 是查找成功, 还是抵达末尾
② counter == 要找到序号,则跳出,所以counter < location ,
nowNode指向的节点为空,则到末尾,则跳出
③④ 这两条语句, 所指向的序号和节点, 是同步的, 位置到或者此节点为空,则跳出
返回值: bool: 是否查找成功? true:false
**************************************************/
bool SpecificLocate_Value(LinkList *L,int location, ElemType &value)
{
int counter = 0;
LinkList *nowNode = L;
while(counter < location && nowNode != NULL)//②
{
counter++; //③ 当前计数的节点
nowNode = nowNode->next;//④当前遍历到的节点
}
if(nowNode == NULL) //①
{
return false;
}
else
{
value = nowNode->data;
return true;
}
}
/**************************************************
⑨函数名:SpecificValue_Location
功 能: 查找特定数据值的节点,并返回其位置
参 数: (1)LinkList *L: 被查找的单链表(2)ElemType e:
注 意: ①从头结点后的第一个节点开始找
②while循环内的两条语句是同步指向的
③当nowNode为空时(到达末尾仍未找到), counter作废
④当nowNode不为空时,跳出时, counter表示所指向节点存在,并符合所需
返回值:
**************************************************/
int SpecificValue_Location(LinkList *L, ElemType value)
{
int counter = 1;
LinkList *nowNode = L->next; //①
while(nowNode != NULL && nowNode->data != value)
{
nowNode = nowNode->next;
counter++; //②
}
if(nowNode == NULL) //③
{
return 0;
}
else //④
{
return counter;
}
}
/**************************************************
⑩函数名: LinkList_InsertElement
功 能: 在单链表特定位置插入节点
参 数: (1)LinkList *&L:要插入的单链表
(2)int location:要插入的位置
(3) ElemType &value:插入的数据
思路: 先在单链表L中,找到第 i-1个节点(不算头结点),若存在这样的节点,
将值为value的节点 插入到其后面
注意: ① 计数器和 nowNode是同步往后移动(从L->next开始算第一个节点),
直到 找到counter = location-1,
②此时 nowNode不为空,则此时nowNode指向
要插入位置的 前一个节点
③ 覆盖指针前, 牢记 nowNode->next里面存放的是后继节点信息,所以要先处理
newNode->next = nowNode->next;
然后我们才能再把 nowNode->next指向新节点 newNode
返回值: bool: 是否存在第i-1个节点,并插入成功? true : false
**************************************************/
bool LinkList_InsertElement(LinkList *&L, int location, ElemType &value)
{
int counter = 0;
LinkList *nowNode = L;
LinkList *newNode;
while((counter < (location-1)) && (nowNode != NULL)) //①
{
counter++;
nowNode = nowNode->next;
}
if(nowNode == NULL)//②
{
return false;
}
else
{
newNode = (LinkList *)malloc(sizeof(LinkList));
newNode->data = value;
newNode->next = nowNode->next;//③
nowNode->next = newNode;
return true;
}
}
/**************************************************
(11)函数名: LinkList_Delete_Location
功 能: 删除特定位置的节点元素
参 数: (1)LinkList *&L:被删除的单链表 (2)int location:特定位置
(3) ElemType &value:被删除的元素值
思路: 找到第location-1个元素, 存储第locataion个元素值(判断null),然后free
链接 location-1 和 location+1
注意: ① counter和指针节点是同步的,要么找到location-1个节点,要么到末尾
② 虽然可能找到location-1个元素,其可能是最后一个元素,从而导致删除失败
需要判断一下,deleteNode是否为空,才能得出是否任务成功
③ 指针覆盖还是老生常谈,先存储一下deleteNode(方便free),
然后指针交替,然后free
返回值: bool: 是否删除成功? true:false
**************************************************/
bool LinkList_Delete_Location(LinkList *&L,int location, ElemType &value)
{
int counter = 0;
LinkList *nowNode = L;
LinkList *deleteNode;
while(counter < (location-1) && nowNode != NULL) //①
{
counter++;
nowNode = nowNode->next;
}
if(nowNode == NULL)
{
return false;
}
else
{
deleteNode = nowNode->next;
if(deleteNode == NULL) //②
{
return false;
}
value = deleteNode->data;
nowNode->next = deleteNode->next; //③
free(deleteNode);
return true;
}
}
/**************************************************
(12)函数名: DeleteMaxNode
功 能: 删除单链表中最大的一个节点
参 数: (1)LinkList *&L:要删除节点的单链表
思路: 四个指针, 最大指针,最大指针前一个节点
目前遍历的指针,遍历指针的前一个节点, 边比较,边替换,边遍历
注意:①避免只有一个头结点,造成空指针替换异常
②③ 顺序不能变,因为③跳出的时候, 会利用到while的非空条件,
避免对比的时候, 出现野指针,直到为空时,即可直接跳出,非空则比较替换
返回值:是否删除成功 ? true:false
**************************************************/
bool DeleteMaxNode(LinkList *&L)
{
LinkList *nowNode,*preNode;
LinkList *maxNode,*preMaxNode;
nowNode = L->next;
preNode = L;
maxNode = nowNode;
preMaxNode = preNode;
if(nowNode == NULL) //①
{
return false;
}
while(nowNode != NULL) //直到末尾
{
if(nowNode->data > maxNode->data) //②
{
maxNode = nowNode;
preMaxNode = preNode;
}
preNode = nowNode; //接着走下一个节点
nowNode = nowNode->next; //③
}
preMaxNode->next = maxNode->next;
free(maxNode);
return true;
}
/**************************************************
(13)函数名:LinkList_sorting
功 能:对单链表中元素进行排序(至少有2个数据节点)
参 数:LinkList *&L:要进行排序的单链表
注意: ① 空表,或者只有一个数据节点,则不需要排序,返回false
② 开始节点必须是头结点,因为我们会用到start_compare->next,
③ 把数据节点(第二个数据节点及以后)和原始链表(头结点+一个数据节点)
④ 在有序表中,一直找到比前一个节点大,比后一个节点小的空挡,
所以时刻对比start_compare->next->data, 并且start_compare->next不能为空
(为空代表到达末尾,交替空指针)
⑤ 顺序不能变, 避免丢失有序表后续信息(指针覆盖的一句话)
详细链接:https://blog.csdn.net/qq_57484399/article/details/127141307
返回值:bool: 是否符合排序标准,并排序成功 ? true: false
**************************************************/
bool LinkList_sorting(LinkList *&L)
{
LinkList *compare,*start_compare,*Remaining_node;
if(L->next == NULL || L->next->next == NULL)//①保证至少有2个数据节点
{
return false;
}
compare = L->next->next;
start_compare = L; //②开始节点必须是头结点
Remaining_node = compare->next;
L->next->next = NULL; //③把数据节点(第二个数据节点及以后)和原始链表(头结点+一个数据节点)
while(compare != NULL)
{
Remaining_node = compare->next;
start_compare = L;
while((start_compare->next != NULL) && (compare->data > start_compare->next->data))
{
start_compare = start_compare->next;
} //④
compare->next = start_compare->next;
start_compare->next = compare; //⑤
compare = Remaining_node;
}
return true;
}
main.cpp测试函数
cpp
#include <stdio.h>
#include "singlelist.h"
/*****************************************
功 能: 把两个有序单链表合并成一个有序单链表
编程人: 王涛
时 间: 2024.4.16
版 本: V1.0
思路:
//定义遍历LA和LB的指针
//轮询遍历LA和LB,数据插入LC
//收尾,LA或LB没遍历完,插入到LC
******************************************/
/**************************************************
函数名: Union_order_singlelist
功 能: 合并两个有序单链表为一个有序单链表
参 数: LinkList *LA,LinkList *LB, LinkList *&LC:LA和LB合并为LC
注 意: ①②③结束条件, 是遍历节点为空
返回值: 无
**************************************************/
void Union_order_singlelist(LinkList *LA,LinkList *LB, LinkList *&LC)
{
// int counter = 0;
//定义遍历LA和LB的指针
LinkList *visit_A = LA->next;
LinkList *visit_B = LB->next;
//定位LC尾指针
LinkList *tail_C;
LinkList *newNode;
//为LC头结点分配空间
LC = (LinkList*)malloc(sizeof(LinkList));
tail_C = LC;
LC->next = NULL;
//轮询遍历LA和LB,数据插入LC
while(visit_A != NULL && visit_B != NULL) //①
{
//为LC新节点分配空间
newNode = (LinkList*)malloc(sizeof(LinkList));
if(visit_A->data < visit_B->data)
{
newNode->data = visit_A->data;
//处理完后,后移,为后面做准备
visit_A = visit_A->next;
//对LC进行尾插法
tail_C->next = newNode;
tail_C = newNode; //涉及指针覆盖,顺序不可调换
// counter++;
// printf("\n第%d个数是 %d \n",counter,newNode->data);
}
else
{
newNode->data = visit_B->data;
//处理完后,后移,为后面做准备
visit_B = visit_B->next;
//对LC进行尾插法
tail_C->next = newNode;
tail_C = newNode;//涉及指针覆盖,顺序不可调换
// counter++;
// printf("\n第%d个数是 %d \n",counter,newNode->data);
}
}
//经过上一步的交替插入,要么两个表交替插入完了,要么是下面两者之一
//LB已经扫描插入完了, LA尚未扫描插入完 , 将其余元素插入到 Lc中
while(visit_A != NULL)//③
{
//为LC新节点分配空间
newNode = (LinkList*)malloc(sizeof(LinkList));
newNode->data = visit_A->data;
//处理完后,后移,为后面做准备
visit_A = visit_A->next;
//对LC进行尾插法
tail_C->next = newNode;
tail_C = newNode; //涉及指针覆盖,顺序不可调换
// counter++;
// printf("\n第%d个数是 %d \n",counter,newNode->data);
}
while(visit_B != NULL) //③
{
//为LC新节点分配空间
newNode = (LinkList*)malloc(sizeof(LinkList));
newNode->data = visit_B->data;
//处理完后,后移,为后面做准备
visit_B = visit_B->next;
//对LC进行尾插法
tail_C->next = newNode;
tail_C = newNode;//涉及指针覆盖,顺序不可调换
// counter++;
// printf("\n第%d个数是 %d \n",counter,newNode->data);
}
//尾结点置空,善后工作
tail_C->next = NULL;
}
int main()
{
LinkList *LA,*LB,*LC;
//定义数组
ElemType test_A[8] = {9,33,5,77,8,22,11,6};
ElemType test_B[5] = {12,30,19,25,66};
//尾插法建立单链表
CreatList_Tail(LA,test_A,8);
//输出展示
printf("\nLA:\n");
DisplayLinkList(LA);
//把单链表变有序
if(LinkList_sorting(LA))
{
printf("\n成功排序LA排序%d个数:\n",LinkListLength(LA));
DisplayLinkList(LA);
}
CreatList_Tail(LB,test_B,5);
printf("\nLB:\n");
DisplayLinkList(LB);
if(LinkList_sorting(LB))
{
printf("\n成功排序LB排序%d个数:\n",LinkListLength(LB));
DisplayLinkList(LB);
}
Union_order_singlelist(LA,LB,LC);
printf("\n成功合并LA和LB并排序%d个数为LC:\n",LinkListLength(LC));
DisplayLinkList(LC);
//释放空间
DestroyLinkList(LA);
DestroyLinkList(LB);
DestroyLinkList(LC);
return 0;
}