单链表基本操作以及合并排序

/*
*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");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值