题目描述
编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef int ElemType;
/*定义结构体*/
typedef struct LNode
{
struct LNode *next;
ElemType num;
}LNode;
/*链表初始化*/
void initList(LNode ** head)
{
if((*head = (LNode *)malloc(sizeof(LNode))) != NULL)
{
(*head)->next = NULL;
}
}
/*求链表中元素的个数*/
int ListLength(LNode *head)
{
int length = 0;
/*指针p指向头节点*/
LNode *p = head;
while(p->next != NULL)
{
length += 1;
p = p->next;
}
return length;
}
/*插入成功return 1,失败return 0*/
/*i代表第i个元素后插入节点,节点num为x*/
int ListInsert(LNode *head,int i,ElemType x)
{
LNode *p,*q;
p = head;
int j = -1;
while((p->next != NULL)&&(j < i-1))
{
p = p->next;
j += 1;
}
/*插入位置非法*/
if(j!=i-1)
return 0;
if((q = (LNode *)malloc(sizeof(LNode))) == NULL)
{
/*分配内存失败*/
printf("Malloc memory failed.\n");
return 0;
}
/*x赋值*/
q->num = x;
/*插入到正确位置*/
q->next = p->next;
p->next = q;
/*插入成功*/
return 1;
}
/*删除链表中第i+1个元素,x保存删除节点的num*/
int ListDel(LNode *head,int i,ElemType *x)
{
LNode *p = head;
LNode *s = NULL;
int j = -1;
while((p->next != NULL)&&(j < i-1))
{
p = p->next;
j++;
}
/*插入位置非法*/
if(j != i-1)
return 0;
/*s指向待删元素*/
s = p->next;
/*待删除元素由x带回*/
*x = s->num;
p->next = p->next->next;
/*释放待删除元素*/
free(s);
s = NULL;
return 1;
}
/*销毁整个链表*/
void destoryList(LNode *head)
{
if(head == NULL)
return;
LNode *p = head;
LNode *s = NULL;
while(p->next != NULL)
{
s = p->next;
p->next = p->next->next;
free(s);
s = NULL;
}
}
/*打印链表中的全部元素*/
void printList(LNode *head)
{
if(head == NULL)
return;
if(ListLength(head) == 0)
{
printf("Empty!\n");
}
/*每10个元素打印一行*/
int cnt = 0;
LNode *p = head;
while(p->next != NULL)
{
p = p->next;
printf("%d ",p->num);
if(cnt % 9 == 0)
printf("\n");
}
}
/*函数用于验证链表基本操作是否正确*/
void checkListValid()
{
LNode *head = NULL;
ElemType x = 0;
/*链表初始化*/
initList(&head);
if(head == NULL)
printf("Error.\n");
/*元素个数为0*/
if(ListLength(head) != 0)
printf("Error.\n");
/*插入10个元素*/
for(int i = 0;i < 10;i++)
{
if(0 == ListInsert(head, i, i+1))
printf("Error.\n");
}
destoryList(head);
/*元素个数为0*/
if(ListLength(head) != 0)
printf("Error.\n");
/*链表中无元素,删除元素非法*/
if(ListDel(head,1,&x) != 0)
printf("Error.\n");
/*插入10个元素*/
for(int i = 0;i < 10;i++)
{
if(0 == ListInsert(head, i, i+1))
printf("Error.\n");
}
printList(head);
/*删除10个元素*/
for(int i = 0;i < 10;i++)
{
if(1 != ListDel(head, 0, &x)|| (x != i+1))
printf("Error.\n");
}
printList(head);
/*插入10个元素*/
for(int i = 0;i < 10;i++)
{
if(0 == ListInsert(head, i, i+1))
printf("Error.\n");
}
/*删除第4个元素,num为4*/
if(1 != ListDel(head, 3, &x)|| (x != 4))
printf("Error.\n");
/*插入元素4,位置4*/
if(0 == ListInsert(head, 3, 4))
printf("Error.\n");
printf("\n");
printList(head);
/*删除最后一个元素*/
if(1 != ListDel(head, 9, &x)|| (x != 10))
printf("Error.\n");
/*删除最后一个元素8*/
if(1 != ListDel(head, 8, &x)|| (x != 9))
printf("Error.\n");
/*删除第三个元素3*/
if(1 != ListDel(head, 2, &x)|| (x != 3))
printf("Error.\n");
printf("\n");
printList(head);
/*销毁链表*/
destoryList(head);
printf("\n");
printList(head);
}
/*找出单链表中倒数第k个节点*/
LNode * nthToLast(LNode *head,int k)
{
LNode *ans = head;
LNode *end = head;
/*k小于0或链表长度小于k犯错*/
if((k<= 0)||(ListLength(head)<k))
return NULL;
/*让end向前移动k个节点*/
for(int i = 0;i < k-1;i++)
{
/*此处应该不用判断,因为前面有判断链表长度*/
if(end == NULL)
return NULL;
end = end->next;
}
/*end指向最后时,ans恰好指向倒数第k个结点*/
while((ans->next != NULL)&&(end->next != NULL))
{
ans = ans->next;
end = end->next;
}
return ans;
}
/*删除单链表中第k个结点,限制条件只能访问第k个结点,不能删除第k个结点*/
bool deleteNode(LNode *head,int k)
{
if((NULL == head)||(head->next == NULL))
return false;
/*指向要删除的结点*/
LNode *ans = head;
LNode *ans_next = head->next;
int len = ListLength(head);
/*长度不符合限制返回false*/
if((k <= 0)||(k>len))
return false;
/*区分是否删除最后一个结点,如果删除最后一个结点,则只用置ans->next = NULL*/
while(k>0 &&(ans->next != NULL)&&(ans_next->next != NULL))
{
ans = ans->next;
ans_next = ans_next->next;
k -= 1;
}
if(k == 0)
{
/*删除结点不是最后一个结点,将后一个结点的内容拷贝到ans->num,删除ans_next*/
ans->num = ans_next->num;
ans->next = ans_next->next;
free(ans_next);
ans_next = NULL;
}
else
{
/*删除的是最后一个元素*/
free(ans_next);
ans->next = NULL;
}
return true;
}
/*将链表中的结点重新排序,小于x的在前,大于等于x的在后*/
LNode * partition(LNode *head,ElemType x)
{
if((head == NULL)||(head->next == NULL))
return NULL;
LNode *last = NULL;
LNode * p = head->next;
/*初始化两个链表*/
LNode * small = NULL;
LNode * big = NULL;
initList(&small);
initList(&big);
while(p != NULL)
{
if(p->num < x)
ListInsert(small,0,p->num);
else
ListInsert(big,0,p->num);
p = p->next;
}
destoryList(head);
last = small;
/*找到small链表中最小元素*/
while(last->next != NULL)
last = last->next;
last->next = big->next;
free(big);
return small;
}
int main(int argc, const char * argv[])
{
//checkListValid();
LNode *head = NULL;
/*链表初始化*/
initList(&head);
ListLength(head);
/*插入10个元素*/
ListInsert(head, 0, 10);
ListInsert(head, 1, 8);
ListInsert(head, 2, 7);
ListInsert(head, 3, 1);
ListInsert(head, 4, 2);
ListInsert(head, 5, 6);
ListInsert(head, 6, 5);
ListInsert(head, 7, 4);
ListInsert(head, 8, 3);
ListInsert(head, 9, 9);
LNode *par = partition(head,5);
printList(par);
destoryList(par);
return 0;
}
算法思路:小于x的结点插入到small链表,大于等于x的结点插入big链表,然后合并small和big,释放原有链表,返回small。