删除节点输出有序结果
给定一个带表头节点的单链表,设head为头指针,data为整型元素
按递增次序输出单链表中的各节点的数据元素,并释放节点所占的存储空间
不允许使用数组做辅助空间
算法思想
应对链表进行遍历,在每趟遍历中查找出整个链表最小值元素,输出并释放节点所占空间;再查找最小值元素,输出并释放节点,如此下去直到链表为空,最后释放头节点所占的存储空间
遍历一遍后,prev的next为最小值节点
输出prev的next的data值
创建指针del保存prev的next
prev的next指向del的next
释放del节点
完成删除
从头开始再次遍历,最终输出的结果成递增排列
void MiniDelete(LinkList &head)
{
// 循环到只剩头节点
while (head->next)
{
// prev保存最小值节点的前驱节点的指针,初始假定prev的next是最小的
LNode* prev = head;
// cur为工作指针
LNode* cur = prev->next;
while (cur->next)
{
// 如果cur的next的值小于prev的next的值,将prev指向cur
if (cur->next->data < prev->next->data)
{
prev = cur;
}
// cur往后移
cur = cur->next;
}
// 输出元素最小值的数据
printf("%d\n", prev->next->data);
// 删除元素值最小的节点,释放节点空间
LNode* del = prev->next;
prev->next = del->next;
free(del);
}
// 释放头节点
free(head);
}
不带头节点单链表排序
已知不带头节点的线性链表head,将该链表按节点数据域大小从小到大重新链接
要求链接过程中不得使用除该链表以外的任何链节点空间
算法思想
本质上是排序问题
链表上排序采用直接插入排序比较方便
首先假定第一个节点有序,然后从第二个节点开始,依次插入到前面有序链表当中,最终达到整个链表有序
创建工作指针cur指向head的next
将第一个节点断开,变为有序链表
cur指针遍历整个待排序链表,直到cur指向NULL
创建指针next保存cur的下一个
创建一个指针指向有序链表中要插入位置的前一个节点
如果cur的值比head的节点的值小
需要将cur的next指向head
将最小的节点变为head节点,即cur节点
cur指向next,继续遍历待排序链表
下一轮循环,next指向cur的next
如果cur的值比head的值大
需要遍历有序链表,查找有序链表中小于cur的值的最后一个节点
用prev指针遍历,直到prev的next指向NULL,或者prev的next的值大于等于cur的值
这样cur直接插入在prev的后面
cur的next指向prev的next
prev的next指向cur
LinkList LinkListSort(LinkList head)
{
// cur是工作指针,指向待排序的当前元素
LNode* cur = head->next;
// 假定第一个元素有序,即链表中现在只有head一个节点
head->next = NULL;
while (cur)
{
// next是cur的后继
LNode* next = cur->next;
// 每次循环将prev重新指向有序链表的第一个节点
LNode* prev = head;
// 处理待排序节点cur比第一个元素节点小的情况
if (prev->data > cur->data)
{
// 链表指针指向最小元素
cur->next = head;
head = cur;
}
else
{
// 查找有序链表中小于cur的值的最后一个节点
while(prev->next && prev->next->data < cur->data)
{
prev = prev->next;
}
// 将当前排序节点链入有序链表中
cur->next = prev->next;
prev->next = cur;
}
// cur指向下一个待排序节点
cur = next;
}
return head;
}
带头节点单链表排序
设L为单链表的头节点地址,其数据节点的数据域都是正整数且无相同的
利用直接插入的原则把该链表整理成数据递增的有序单链表的算法
算法思想
单链表带头节点,要求用直接插入排序原则,从第二个节点开始,将各节点依次插入到有序链表中
LinkList LinkListInsertSort(LinkList &L)
{
// 如果L不为空表
if (L->next)
{
// cur指向第一节点的后继
LNode* cur = L->next->next;
// 认为第一元素有序,从第二个元素开始依次插入
L->next->next = NULL;
}
while (cur)
{
// 暂存cur的后继
LNode* next = cur->next;
LNode* prev = L;
// 查找插入的位置
while (prev->next && prev->next->data < cur->data)
{
prev = prev->next;
}
// 将cur节点链入链表
cur->next = prev->next;
prev->next = cur;
}
cur = next;
return L;
}
单链表快排
给一个链表的头节点head,将其按升序排列并返回排序后的链表
算法思想
遍历获取链表节点值,利用快排函数,qsort进行排序,再存储
int compare(void* a, void* b)
{
// 排升序
return *(int*)a - *(int*)b;
}
LinkList sortList(LinkList &head)
{
// 若该链表是空表,返回NULL
if (head == NULL)
return NULL;
// 创建一个足够大的数组,全部初始化为0
int num[50000] = {0};
int numsize = 0;
// 创建一个工作指针cur指向head头节点
LNode* cur = head;
// 开始遍历,将链表中的数据存储到数组中
while (cur)
{
num[numsize++] = cur->val;
cur = cur->next;
}
// qsort将数组中的数据排序
qsort(num, numsize, sizeof(int), compare);
// 初始化cur指针和数组下标
cur = head;
numsize = 0;
// 再遍历链表,将数组中的值依次存储到节点中
while (cur)
{
cur->val = num[numsize++];
cur = cur->next;
}
// 返回头节点
return head;
}