将单链表按基准划分

将单链表按基准划分(C语言实现)

目的:掌握单链表的应用和算法设计
内容:以给定值x为基准将单链表分割为两部分,所有小于x的结点排在大于或等于x的结点之前。
思路:创建一个新的头结点,将小于基准的结点接到新的头结点之后并将其从原本的链表中删除,然后再将新的链表接到原本的链表之前。

算法实现:
bool DivideList(LinkNode*& L, ElemType x)	//L为传入的链表头结点,x为传入的基准
{
	if (L->next==NULL) {
		printf("单链表不存在。\n");
		return false;
	}
	LinkNode* p = NULL, * q = NULL, * r = NULL;	//p为工作指针,q为小于基准的数的头结点,r为尾指针
	p = L;
	//直到申请成功,因为malloc可能申请失败
	while (!q) {
		q = (LinkNode*)malloc(sizeof(LinkNode));
	}
	r = q;	//r指向小于基准的链表的尾巴
	//p从第一个有效结点开始扫描整个链表,直到p后无结点为空
	while (p->next) {
		if (p->next->data < x) {
			r->next = p->next;		//将p接到尾巴后面
			r=r->next;				//尾巴后移
			p->next= p->next->next;	//将该结点从L中截取出去
			r->next = NULL;			//将尾巴与原链表之间的关系切断
		}
		else
			p = p->next;			//p后移
	}
	//将小于基准的链表接到大于等于基准的链表的前面
	r->next = L->next;	//小于基准的链表的尾巴与大于等于基准的链表相连
	L->next = q->next;	//将整体接到头结点后
	free(q);			//释放小于基准的链表的头结点
	return true;
}

bool DivideList(LinkNode*& L, ElemType x)中用到了引用参数,引用参数在C++里才有,所以源代码文件格式应为".cpp"。

与主函数相结合
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;
}LinkNode;

bool DivideList(LinkNode*& L, ElemType x);	//L为传入的链表头结点,x为传入的基准
bool InitList(LinkNode*& L);		//链表产生
bool DispList(LinkNode* L);			//链表输出

int main(int argc, const char* argv[])
{
	LinkNode* L = NULL;
	int x;
	bool flag = false;
	InitList(L);
	printf("请输入基准。\n");
	scanf("%d", &x);
	flag = DivideList(L, x);
	if (flag)
		printf("算法执行成功。\n");
	else
		printf("算法执行失败。\n");
	DispList(L);
	return 0;
}

bool InitList(LinkNode*& L)		//建立单链表
{
	while (!L) {
		L = (LinkNode*)malloc(sizeof(LNode));
	}
	L->next = NULL;
	int i, n;
	LinkNode* p = NULL, * q = NULL;
	q = L;
	printf("请输入数据规模:\n");
	scanf("%d", &n);
	printf("请输入数据:\n");
	for (i = 0; i < n; i++) {
		while (!p) {
			p = (LinkNode*)malloc(sizeof(LNode));
		}
		scanf("%d", &p->data);
		q->next = p;
		q = p;
		p = q->next = NULL;
	}
	return true;
}
bool DispList(LinkNode* L)		//输出单链表
{
	LinkNode* p = L->next;
	while (p) {
		printf("\t%d", p->data);
		p = p->next;
	}
	printf("\n");
	return true;
}
bool DivideList(LinkNode*& L, ElemType x)	//L为传入的链表头结点,x为传入的基准
{
	if (L->next==NULL) {
		printf("单链表不存在。\n");
		return false;
	}
	LinkNode* p = NULL, * q = NULL, * r = NULL;	//p为工作指针,q为小于基准的数的头结点,r为尾指针
	p = L;
	//直到申请成功,因为malloc可能申请失败
	while (!q) {
		q = (LinkNode*)malloc(sizeof(LinkNode));
	}
	r = q;	//r指向小于基准的链表的尾巴
	//p从第一个有效结点开始扫描整个链表,直到p后无结点为空
	while (p->next) {
		if (p->next->data < x) {
			r->next = p->next;		//将p接到尾巴后面
			r=r->next;				//尾巴后移
			p->next= p->next->next;	//将该结点从L中截取出去
			r->next = NULL;			//将尾巴与原链表之间的关系切断
		}
		else
			p = p->next;			//p后移
	}
	//将小于基准的链表接到大于等于基准的链表的前面
	r->next = L->next;	//小于基准的链表的尾巴与大于等于基准的链表相连
	L->next = q->next;	//将整体接到头结点后
	free(q);			//释放小于基准的链表的头结点
	return true;
}
  • 11
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为两部分,比基准小的节点在前面,大于等于基准的节点在后面。可以使用额外的空间,要求算法时间复杂度为O(n)。 好的,您的问题是如何将单链表基准划分为两部分,比基准小的节点在前面,大于等于基准的节点在后面。算法时间复杂度为O(n),可以使用额外的空间。 以下是一个可能的解决方案: 建立两个新的链表,分别为small和big。遍历原始链表,将小于基准的节点加入small链表,将大于等于基准的节点加入big链表。最后将small链表的尾部指向big链表的头部,即可得到新的链表。同时,还需要保持原始链表的顺序不变。时间复杂度为O(n),需要额外的空间来存储两个新链表。 以下是代码实现的示例: ``` struct LinkedListNode { int value; LinkedListNode* next; }; LinkedListNode* partitionLinkedList(LinkedListNode* head, int pivot) { LinkedListNode* smallHead = nullptr; LinkedListNode* smallTail = nullptr; LinkedListNode* bigHead = nullptr; LinkedListNode* bigTail = nullptr; while (head != nullptr) { LinkedListNode* nextNode = head->next; head->next = nullptr; if (head->value < pivot) { if (smallHead == nullptr) { smallHead = head; smallTail = head; } else { smallTail->next = head; smallTail = head; } } else { if (bigHead == nullptr) { bigHead = head; bigTail = head; } else { bigTail->next = head; bigTail = head; } } head = nextNode; } if (smallHead == nullptr) { return bigHead; } else { smallTail->next = bigHead; return smallHead; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值