单链表是一种重要的数据结构,为了防止忘记单链表,写一篇博客用来复习。本文实现了单链表的创建、插入、删除、排序、倒置以及合并等功能,如有遗漏,可以根据单链表的思想自行实现。
单链表采用结构指针来实现,首先定义一个结构体,里面存放数据和指向下一个结点的指针。
typedef struct LNode
{
int data;
struct LNode* next;
}LNode, *LinkList;
实现代码
#include <iostream>
typedef struct LNode
{
int data; // 数据域
struct LNode* next; // 指针域
}LNode, *LinkList;
// 创建空表
LinkList CreateHead()
{
LinkList head = (LinkList)malloc(sizeof(LNode));
head->next = NULL;
return head;
}
// 头插法创建链表
LinkList CreateList_Head()
{
int i, j;
LinkList h = CreateHead();
printf("Please input the number of element: ");
scanf("%d", &j);
for (i = 0; i < j; ++i)
{
LinkList p = (LinkList)malloc(sizeof(LNode));
p->data = rand() % 100; // 也可以修改为用户输入
p->next = h->next;
h->next = p;
}
return h;
}
// 尾插法创建链表
LinkList CreatList_Tail()
{
int i, j;
LinkList h = CreateHead();
LinkList q = h;
printf("Please input the number of element: ");
scanf("%d", &j);
for (i = 0; i < j; ++i) {
LinkList p = (LinkList)malloc(sizeof(LNode));
p->data = rand() % 100;
printf("%d ", p->data);
q->next = p;
q = p;
}
q->next = NULL; // q节点的指针域指向链表尾
printf("\n");
return h;
}
// 遍历链表
void TraverseList(LinkList h) {
int i = 0;
LinkList p;
if (h == NULL)
{
printf("Not found list!");
return;
}
p = h->next;
printf("Linklist elements are: ");
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
// 清空链表
void ClearList(LinkList &h)
{
LinkList p, q = NULL;
p = h->next;
while (p)
{
q = p;
p = p->next;
free(q);
}
h->next = NULL; // 头结点指针域为空
printf("Linklist has been cleared!\n");
}
// 在第i个位置前插入一个元素
void InsertNode(LinkList &h, int i, int e) {
int j = 1;
LinkList p, q;
p = h; // p指向头结点
while (p && j < i) //寻找第i-1个节点
{
p = p->next;
++j;
}
q = (LinkList)malloc(sizeof(LNode));
q->data = e;
q->next = p->next;
p->next = q;
printf("Successfully insert %d !\n", q->data);
}
// 删除第i个结点
void DeleteNode(LinkList &h, int i)
{
int j = 1;
LinkList p, q;
p = h;
while (p && j < i) // 和插入一样 先找到第i-1个结点
{
p = p->next;
++j;
}
q = p->next;
p->next = q->next;
printf("Successfully delete this element%d !\n", q->data);
free(q);
}
// 查找中间元素
void SearchMidElement(LinkList &h)
{
int i = 0;
LinkList p, q; // q为快指针,p为慢指针
p = q = h;
while (q)
{
if (q->next->next) // q的下下个结点存在时
{
i++;
q = q->next->next;
p = p->next;
if (q->next == NULL) // 如果q的下个结点不存在 则结点数为偶数
{
printf("Mid elements are: %d, %d\n", p->data, p->next->data);
break;
}
}
else
{
i++;
printf("Mid elements is: %d\n", p->next->data);
break;
}
}
}
// 翻转链表
void ReverseList(LinkList &h)
{
LinkList p, q;
q = h; // q为前驱指针
p = h->next;
h->next = NULL; // 将h置为空表 重新插入
while (p)
{
q = p;
p = p->next;
q->next = h->next;
h->next = q;
}
}
// 逆转指针方向
void ReverseList_p(LinkList &h)
{
LinkList p, pr, pn;
pr = h;
p = h->next;
while (p)
{
pn = p->next; // pn 的作用为保存 p 的下一个结点的位置
p->next = pr; // p 的下一个结点改为前一个结点
pr = p; // 指针向后推进
p = pn;
}
if (h->next)
{
h->next->next = NULL;
h->next = pr;
}
}
// 升序排序
void SortList(LinkList &h)
{
LinkList p, q, qr, pr;
pr = h;
p = h->next;
h->next = NULL; // 断开头结点
while (p)
{
pr = p;
p = p->next; // 摘掉pr 插入到h中
qr = h;
q = h->next;
while (q && q->data < pr->data)
{
qr = q;
q = q->next;
}
pr->next = q;
qr->next = pr;
}
}
// 将两个递增有序排列的链表合并成一个升序序列的链表
void MergeList(LinkList ha, LinkList hb, LinkList &hc)
{
LinkList pa, pb, pc, p;
pa = ha->next;
pb = hb->next;
pc = hc;
while (pa && pb)
{
if (pa->data < pb->data) // 如果此时pa的data更小 则摘下结点接到pc上
{
p = pa;
pa = pa->next;
}
else
{
p = pb;
pb = pb->next;
}
pc->next = p;
pc = p;
}
if (pa) pc->next = pa;
if (pb) pc->next = pb;
ha->next = hb->next = NULL;
}
// 删除链表中所有值大于mink且小于maxk的元素
void DeleteElemByRange(LinkList &h, int mink, int maxk)
{
LinkList p, q, pr;
if (mink > maxk)return;
pr = h;
p = h->next;
while (p && p->data < maxk) {
if (p->data > mink) {
pr->next = p->next;
q = p;
p = p->next;
free(q);
}
else {
pr = p;
p = p->next;
}
}
}
// 删除升序表中的重复元素
void DeleteRepeatElem(LinkList &h)
{
LinkList p, q, pr;
pr = h;
p = h->next;
while (p) {
pr = p;
p = p->next; // pr和p分别指向第一和第二个节点
if (p && p->data == pr->data) { // 如果p不为空且pr=p 则删除p
pr->next = p->next;
q = p;
p = p->next;
free(q);
}
}
}
int main()
{
LinkList L1 = CreateList_Head();
SortList(L1);
TraverseList(L1);
LinkList L2 = CreateList_Head();
SortList(L2);
TraverseList(L2);
LinkList L3 = CreateHead();
MergeList(L1, L2, L3);
TraverseList(L3);
return 0;
}