链表的常用操作实现及测试:
- 单链表的创建及初始化
- 节点插入
- 节点删除
- 节点查询
- 节点修改
- 链表排序
- 链表的遍历并输出
- 反转链表
- 合并两个有序链表,使新链表仍保持有序
- 删除单链表L中的重复元素
代码(C语言):
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode* next;
} LNode, * LinkList;
LinkList Create_LinkList(int n);
void Print_LinkList(LinkList L);
int Insert_LinkList(LinkList L, int i, ElemType e);
int Delete_LinkList(LinkList L, int i, ElemType* e);
int Locate_LinkList(LinkList L, ElemType e);
int Modify_LinkList(LinkList L, int i, ElemType e);
int GetPosition_LinkList(LinkList L, ElemType e);
void DuplicateRemoveLinkList(LinkList L);
LinkList ReverseLinkList(LinkList L);
void BubbleSort_LinkList(LinkList L);
void SelectSort_LinkList(LinkList L);
LNode* Merge(LNode* head1, LNode* head2);
LinkList MergeSort_LinkList(LinkList L);
int Count_LinkList(LinkList L, ElemType x);
void Test1();
void Test2();
void Test3();
void menu();
int main(void)
{
menu();
return 0;
}
LinkList Create_LinkList(int n)
{
LNode* p, * q;
int i = 0;
LNode* L = (LNode*)malloc(sizeof(LNode));
L->next = NULL;
q = L;
printf("输入单链表各元素的值:");
for (i = 0; i < n; i++)
{
p = (LNode*)malloc(sizeof(LNode));
scanf("%d", &p->data);
p->next = NULL;
q->next = p;
q = p;
}
return L;
}
void Print_LinkList(LinkList L)
{
LNode* p;
p = L->next;
printf("\n输出单链表中各元素的值:");
while (p)
{
printf("%d ", p->data);
p = p->next;
}
}
int Insert_LinkList(LinkList L, int i, ElemType e)
{
LNode* p = L;
int j = 1;
while (p && j < i)
{
p = p->next;
j++;
}
if (!p || j > i) return 0;
LNode* s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
int Delete_LinkList(LinkList L, int i, ElemType* e)
{
int j = 1;
LNode* p = L;
while (p->next && j < i)
{
p = p->next;
j++;
}
if (!(p->next) || j > i) return 0;
LNode* q = p->next;
*e = q->data;
p->next = q->next;
free(q);
return 1;
}
int Locate_LinkList(LinkList L, ElemType e)
{
int i = 0;
LNode* p = L;
while (p && p->data != e)
{
p = p->next;
i++;
}
if (!p) return 0;
else return i;
}
int Modify_LinkList(LinkList L, int i, ElemType e)
{
LNode* p = L;
int j = 0;
while (j++ < i && p)
{
p = p->next;
}
if (i < 1 || p == NULL) return 0;
p->data = e;
return 1;
}
int GetPosition_LinkList(LinkList L, ElemType e)
{
LNode* p = L;
int t = 0;
while (p->next != NULL)
{
t++;
if (e <= (p->next->data)) return t;
p = p->next;
}
return t + 1;
}
void DuplicateRemoveLinkList(LinkList L)
{
LNode* p, * q;
p = L->next;
while (p != NULL)
{
q = p;
while (q->next != NULL)
{
if (p->data == q->next->data)
{
LNode* tem = q->next;
q->next = q->next->next;
free(tem);
}
else
{
q = q->next;
}
}
p = p->next;
}
}
LinkList ReverseLinkList(LinkList L)
{
LNode* head = L->next;
LNode* prev = NULL;
LNode* curr = head;
while (curr)
{
LNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
L->next = prev;
return L;
}
void BubbleSort_LinkList(LinkList L)
{
if (L == NULL || L->next == NULL) return;
LNode* p = NULL, * q = NULL;
for (p = L->next; p->next != NULL; p = p->next)
{
int flag = 0;
for (q = L->next; q->next != NULL; q = q->next)
{
if (q->data > q->next->data)
{
ElemType temp = q->data;
q->data = q->next->data;
q->next->data = temp;
flag = 1;
}
}
if (flag == 0) return;
}
}
void SelectSort_LinkList(LinkList L)
{
if (L == NULL || L->next == NULL) return;
LNode* p = NULL, * q = NULL;
for (p = L->next; p->next != NULL; p = p->next)
{
for (q = p->next; q != NULL; q = q->next)
{
if (p->data > q->data)
{
ElemType temp = p->data;
p->data = q->data;
q->data = temp;
}
}
}
}
LNode* Merge(LNode* head1, LNode* head2)
{
LNode* dummyHead = (LNode*)malloc(sizeof(LNode));
dummyHead->data = 0;
LNode* temp = dummyHead, * temp1 = head1, * temp2 = head2;
while (temp1 != NULL && temp2 != NULL)
{
if (temp1->data <= temp2->data)
{
temp->next = temp1;
temp1 = temp1->next;
}
else
{
temp->next = temp2;
temp2 = temp2->next;
}
temp = temp->next;
}
if (temp1 != NULL)
{
temp->next = temp1;
}
else if (temp2 != NULL)
{
temp->next = temp2;
}
return dummyHead->next;
}
LinkList MergeSort_LinkList(LinkList L)
{
LNode* head = L->next;
if (head == NULL)
{
return head;
}
int length = 0;
LNode* node = head;
while (node != NULL)
{
length++;
node = node->next;
}
LNode* dummyHead = (LNode*)malloc(sizeof(LNode));
dummyHead->next = head;
for (int subLength = 1; subLength < length; subLength <<= 1)
{
LNode* prev = dummyHead, * curr = dummyHead->next;
while (curr != NULL)
{
LNode* head1 = curr;
for (int i = 1; i < subLength && curr->next != NULL; i++)
{
curr = curr->next;
}
LNode* head2 = curr->next;
curr->next = NULL;
curr = head2;
for (int i = 1; i < subLength && curr != NULL && curr->next != NULL; i++)
{
curr = curr->next;
}
LNode* next = NULL;
if (curr != NULL)
{
next = curr->next;
curr->next = NULL;
}
LNode* merged = Merge(head1, head2);
prev->next = merged;
while (prev->next != NULL)
{
prev = prev->next;
}
curr = next;
}
}
return dummyHead;
}
int Count_LinkList(LinkList L, ElemType x)
{
LNode* p;
int cnt = 0;
p = L->next;
while (p)
{
if (p->data == x) cnt++;
p = p->next;
}
return cnt;
}
void Test1()
{
LinkList L;
int n = 0, status = 0, i = 0;
ElemType e = 0, x = 0;
printf("请输入单链表的长度:n=");
scanf("%d", &n);
L = Create_LinkList(n);
Print_LinkList(L);
printf("\n\n1 测试插入功能\n输入待插入的元素的值:");
scanf("%d", &e);
printf("输入待插入的位置:");
scanf("%d", &i);
status = Insert_LinkList(L, i, e);
if (status)
{
printf("插入成功!");
Print_LinkList(L);
}
else printf("插入失败!");
printf("\n\n2 测试删除功能\n输入待删除元素的位置:");
scanf("%d", &i);
status = Delete_LinkList(L, i, &e);
printf("待删除元素的值为:%d\n", e);
if (status)
{
printf("删除成功!");
Print_LinkList(L);
}
else printf("删除失败!");
printf("\n\n3 测试查询功能\n输入待查询的元素的值:");
scanf("%d", &e);
int position = Locate_LinkList(L, e);
if (position) printf("该元素在链表中的位置为:第%d个元素", position);
else printf("未查询到该元素!");
printf("\n\n4 测试修改功能\n输入待修改元素的位置:");
scanf("%d", &i);
printf("输入修改后的值:");
scanf("%d", &e);
status = Modify_LinkList(L, i, e);
if (status)
{
printf("修改成功!");
Print_LinkList(L);
}
else printf("输入的位置不合法,修改失败!");
printf("\n\n5 测试排序功能");
L = MergeSort_LinkList(L);
printf("\n归并排序结束!");
Print_LinkList(L);
printf("\n\n6 将元素e插入至有序单链表L中,并使L仍保持有序:\n");
printf("输入元素e的值:");
scanf("%d", &e);
position = GetPosition_LinkList(L, e);
status = Insert_LinkList(L, position, e);
if (status)
{
printf("插入成功!");
Print_LinkList(L);
}
else printf("插入失败!");
printf("\n\n7 测试反转链表功能\n反转链表后");
L = ReverseLinkList(L);
Print_LinkList(L);
printf("\n\n8 计算单链表L中数据域值为x的节点个数:\n");
printf("输入x的值:");
scanf("%d", &x);
int cnt = Count_LinkList(L, x);
printf("单链表L中数据域值为%d的个数为:%d个\n\n", x, cnt);
system("pause");
}
void Test2()
{
int lenA = 0, lenB = 0;
LinkList LA;
LinkList LB;
printf("创建单链表LA,输入其长度:");
scanf("%d", &lenA);
LA = Create_LinkList(lenA);
printf("对单链表LA进行冒泡排序:");
BubbleSort_LinkList(LA);
Print_LinkList(LA);
printf("\n\n创建单链表LB,输入其长度:");
scanf("%d", &lenB);
LB = Create_LinkList(lenB);
printf("对单链表LB进行直接选择排序:");
SelectSort_LinkList(LB);
Print_LinkList(LB);
printf("\n\n合并单链表LA和LB,使新链表仍保持有序!\n合并成功!");
LinkList LC = (LNode*)malloc(sizeof(LNode));
LC->next = Merge(LA->next, LB->next);
Print_LinkList(LC);
printf("\n\n");
system("pause");
}
void Test3()
{
LinkList L;
int n = 0;
printf("请输入单链表的长度:n=");
scanf("%d", &n);
L = Create_LinkList(n);
Print_LinkList(L);
DuplicateRemoveLinkList(L);
printf("\n去重后:");
Print_LinkList(L);
printf("\n\n");
system("pause");
}
void menu()
{
system("cls");
int sel = 0;
printf("1 测试单链表的创建及初始化、节点插入、节点删除、节点查询、节点修改、链表排序、链表遍历并输出、反转链表等功能\n");
printf("2 合并两个有序链表,使新链表仍保持有序\n");
printf("3 删除单链表L中的重复元素\n");
printf("4 退出\n");
printf("输入你的选择:");
scanf("%d", &sel);
while (sel < 1 || sel > 4)
{
printf("输入有误,重新输入:");
scanf("%d", &sel);
}
switch (sel)
{
case 1:
Test1();
menu();
break;
case 2:
Test2();
menu();
break;
case 3:
Test3();
menu();
break;
case 4:
exit(0);
default:
menu();
break;
}
}
执行结果:
测试1:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/92705998b049e807d50168cfe245aa09.png)
测试2:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/42ad9a7fd5ac210eddbd4a627b025fbb.png)
测试3:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ca2d57ad9a33fded1dfd60ecde132159.png)