/*
*author:y
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#include <windows.h>
typedef struct node {
int data;
struct node* next;
}NODE, * LinkList;
//创建带头节点的单链表,并赋值十个随机数
LinkList createListWithHead(LinkList L) {
int i, num = 10;
LinkList p;
L = (NODE*)malloc(sizeof(NODE));
L->next = NULL;//初始化头节点
p = L->next;
for (i = 0; i < num; i++)//随机生成10个数据
{
LinkList temp = (NODE*)malloc(sizeof(NODE));//创建新元素的节点空间
temp->data = rand() % 101;//新节点赋值100以内的随机数
temp->next = p;
L->next = temp;
p = temp;
}
return L;
}
//遍历链表
void reverse(LinkList L) {
LinkList p = L;
p = p->next;
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//通过输入的数值去表中查找该值是否在表中,若找到该值返回其表中位置,反之返回0
int findListByVal(LinkList L, int v) {
LinkList p;
int i = 1;
p = L->next;
while (p != NULL)//当节点为空时停止循环
{
if (p->data == v)return i;//该值存在退出循环返回其位置
i++;
p = p->next;
}
return -1;
}
//通过输入的位置去表中查找该位置的值
LinkList findListByPos(LinkList L, int k) {
LinkList p;
int i = 1;
p = L->next;
while (p && i < k)
{
p = p->next;
i++;
}
if (p && i == k)return p;
return NULL;
}
/*单链表插入运算
* 将元素newElem插入表中的第k个元素之前,若成功则返回0,否则返回-1
*/
int insertList(LinkList L, int k, int newElem) {
LinkList p, s;
if (k == 1)p = L;//插入位置为1,直接将元素newElem插入到第1个元素之前
else p = findListByPos(L, k - 1);//查找表中的第k-1个元素并令p指向该元素节点
if (!p)return-1;//表中不存在k-1个元素,不满足运算直接退出
s = (NODE*)malloc(sizeof(NODE));//创建新元素的节点空间
if (!s)return-1;
s->data = newElem;
s->next = p->next;
p->next = s;//将元素newELem插入第k-1个元素之后
return 0;
}
/*单链表删除运算
*删除表中的第k个元素节点,若成功则返回0,否则返回-1
*/
int deleteList(LinkList L, int k) {
LinkList p, q;
if (k == 1)p = L;//删除第一个元素节点
else p = findListByPos(L, k - 1);//查找表中的第k-1个元素并令p指向该元素节点
if (!p || !p->next)return-1;//表中不存在第k个元素
q = p->next;//令q指向第k个元素节点
p->next = q->next;
free(q);//删除节点
return 0;
}
/*------------------------------------------
*归并排序
*采用分治和递归的思想
*先将链表的元素进行逐层折半分组直至分为单个有序的节点,再从最小的分组开始比较排序
*以升序为例将较大的元素合并在较小元素之后,逐层进行比较排序合并。最终合并成一个大而有序的组合。
*/
LinkList mergeList(LinkList L1, LinkList L2) {
//当L1|L2链表没有元素需要组合后继续L2|L1的链表组合
if (L1 == NULL)
{
return L2;
}
if (L2 == NULL)
{
return L1;
}
//用于存储新链表的头节点指针
LinkList head;
//小的值链接到下一个
if (L1->data < L2->data)//左半边组合的第一个剩余元素更小
{
head = L1;
head->next = mergeList(L1->next, L2);//继续排序组合L1->next,和L2的元素大小
}
else//右半边组合的第一个剩余元素更小
{
head = L2;
head->next = mergeList(L1, L2->next);
}
return head;
}
LinkList sortList(LinkList headref) {
if (headref == NULL || headref->next == NULL)
{
return headref;
}
//定义三个指针分别指向链表的0、1、2位地址
LinkList slow = headref, mid = headref->next, fast = headref->next->next;
//通过循环使fast指针走到尾时,取到中间节点的前一个节点
while (fast && fast->next)
{
slow = slow->next;
mid = mid->next;
fast = fast->next->next;
}
//将链表一分为二,[slow,mid)为左半边链表组合,[mid,fas)为右半边链表组合
slow->next = NULL;
//通过递归不断切割左边的组合直至只剩单个有序元素
LinkList node1 = sortList(headref);
//通过递归不断切割右边的组合直至只剩单个有序元素
LinkList node2 = sortList(mid);
//重组新的有序链表组合
LinkList newList = mergeList(node1, node2);
return newList;
}
/*------------------------------------------*/
void checkEnter(int f, int num) {
if (f == 0)return;//正常退出
if (f == -1) {
printf("Please check your enter !!!\n");//异常退出
return;
}
if (f > 0)//查找返回
printf("%d is in the %d position in the list \n", num, f);
}
void q1(LinkList L1) {
int num, pos;
printf("-------------- Question 01 Operation of a singly linked list ---------------\n");
printf("There are 10 numbers in the list: \n");
reverse(L1);
//根据用户输入的数值查找该值是否在表中
printf("Please enter the number you want to find: \n");
scanf_s("%d", &num);
checkEnter(findListByVal(L1, num), num);
//根据用户输入的位置和值插入到表中
printf("Please enter the postion and number you want to insert: \n");
scanf_s("%d%d", &pos, &num);
checkEnter(insertList(L1, pos, num), NULL);
reverse(L1);
//根据用户输入的位置删除表中该位置的值
printf("Please enter the position of the number you want to delete: \n");
scanf_s("%d", &pos);
checkEnter(deleteList(L1, pos), NULL);
reverse(L1);
}
void q2(LinkList L1, LinkList L2) {
LinkList L3 = NULL;
printf("-------------- Question 02 Merge sort L1 and L2 ---------------\n");
reverse(L1);
reverse(L2);
printf("---The following is sorted ones\n");
sortList(L1);
reverse(L1);
sortList(L2);
reverse(L2);
printf("---The following is Merge sorted ones\n");
L3 = mergeList(L1, L2);
reverse(L3->next);
}
void main() {
LinkList L1 = NULL, L2 = NULL;
int opt, flag = 1;
srand(time(NULL));
L1 = createListWithHead(L1);
L2 = createListWithHead(L2);
while (flag) {
system("cls");
printf("[1] Check Q1 about Operation of a singly linked list\n");
printf("[2] Check Q2 about Merge sort L1 and L2\n");
printf("[0]--------Exit program-------- \n");
scanf_s("%d", &opt);
switch (opt) {
case 0:flag = 0; printf("See you next time ~\n"); break;
case 1:q1(L1); break;
case 2:q2(L1, L2); break;
default:printf("Please check your options!!!\n"); break;
}
system("pause");
}
}
单链表基本操作以及合并排序
最新推荐文章于 2025-12-07 23:51:09 发布
博客围绕C语言展开,涉及数据结构与算法知识,着重探讨链表及排序算法相关内容,在信息技术领域,这些知识对程序开发和优化有重要作用。
1972

被折叠的 条评论
为什么被折叠?



