设有一个正整数序列组成的有序单链表(按递增次序有序,且允许有相等的整数存在),试编写能实现下列功能的算法 :(要求用最少的时间和最小的空间)
(1)确定在序列中比正整数x大的数有几个(相同的数只计算一次,如序列{20,20,17,16,15,15,11,10,8,7,7,5,4}中 比10大的数有5个);
(2)在单链表将比正整数x小的数按递减次序排列;
(3)将正整数比x大的偶数从单链表中删除。
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct node
{
ElemType data;
struct node *next;
} Node, *LinkList;
int Count(LinkList L, int x);//计算比x大的数的个数
void DisplayList(LinkList L);//打印链表
void Reverse(LinkList *L, int x);//把比x小的序列倒置
void Delete_Than(LinkList *L, int x);//删除比x大的偶数
int main()
{
int input;
LinkList L = NULL;
LinkList node;
printf("请按升序输入一串数,中间以空格间隔,以-1结尾\n");
scanf("%d", &input);
while(1)
{
static LinkList tail;//静态定义一个尾指针
node = (LinkList)malloc(sizeof(Node));
node ->data = input;
if(L == NULL)
{
L = node;
node->next = NULL;
}
else
{
tail->next = node;
node->next = NULL;
}
tail = node;
/********************上为尾插法*******************/
scanf("%d", &input);
if(input == -1)
break;//输入-1时,结束循环
while(input < tail->data)
{
printf("输入错误,重新输入输错的部分\n");
scanf("%d", &input);
}//如果输入的值小于前一个数,则输入错误
}
printf("现在的链表为\n");
DisplayList(L);
int x;//确定x
printf("请输入x\n");
scanf("%d", &x);
int a = Count(L, x);
printf("比x大的数共%d个\n", a);
printf("现在倒置比x小的数据\n");
Reverse(&L, x);
printf("现在的链表为\n");
DisplayList(L);
printf("现在删除比x大的偶数\n");
Delete_Than(&L,x);
printf("现在的链表为\n");
DisplayList(L);
return 0;
}
void DisplayList(LinkList L)
{
LinkList node = L;
while(node != NULL)
{
printf("%d ", node->data);
node = node->next;
}
printf("\n");
}
void Reverse(LinkList *L, int x)
{
LinkList r = *L;
LinkList p = *L;
LinkList q = NULL;
while(p->data < x)
{
q = p;
p = p->next;
}//此时,p是x所在结点或比x小的第一个节点,q为p的前节点
/*p->data是否等于a会有不同的插入,可画图进行深刻了解*/
if(p->data == x)
{
while(*L != q)
{
*L = (*L)->next;//头结点后移
r->next = q->next;//r为头结点,把头结点插入到q的后面
q->next = r;//
r = *L;//再把r指向头结点
}
}
else//p->data小于x时
{
while(*L != p)
{
*L = (*L)->next;//头结点后移
r ->next = p->next;//把头结点插入到p后
p->next = r;
r = *L;//再把r指向头结点
}
}
}
int Count(LinkList L, int x)
{
int num = 0;
int e;//取出比x大的数
LinkList p = L;
while(p->data <= x)
{
p = p->next;
}//此时,p->data大于x
e = p->data;取出此时的p->data
num++;计数器加一
p = p->next;//指向下个节点
while(p)
{
if(p->data > e)//判断p->data > e的时候
{
e = p->data;//取出e;
num++;计数器加1
}
p = p->next;//指向下个节点
}
return num;//返回比x大的数的个数
}
//删除比x大的偶数
void Delete_Than(LinkList *L, int x)
{
LinkList q = NULL;
LinkList p = *L;
while(p->data <= x)
{
q = p;
p = p->next;
}//p指向比x大的节点,q为p的前节点
while(p)
{
if(p->data % 2 == 0)//判断p->data是比x大的偶数
{
LinkList temp = p;//先把p赋给temp;
q->next = p->next;//删除p节点
p = q->next;//把q的下个节点赋给p
free(temp);//释放空间
}
else//不是偶数
{
//两个指针后移
q = q->next;
p = p->next;
}
}
}