254 lines
6.3 KiB
C++
254 lines
6.3 KiB
C++
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
typedef struct LNode
|
||
{
|
||
int data; //数据域
|
||
struct LNode *next; //指针域
|
||
}LNode,*LinkList; // LinkList为指向LNode类型的指针类型
|
||
|
||
// 初始化四个链表L、M、N、H
|
||
void chushihua(LinkList &L, LinkList &M, LinkList &N, LinkList &H)
|
||
{
|
||
//todo list 1: 为四个链表分配头节点并初始化
|
||
L = (LinkList)malloc(sizeof(LNode));
|
||
L->next = NULL;
|
||
M = (LinkList)malloc(sizeof(LNode));
|
||
M->next = NULL;
|
||
N = (LinkList)malloc(sizeof(LNode));
|
||
N->next = NULL;
|
||
H = (LinkList)malloc(sizeof(LNode));
|
||
H->next = NULL;
|
||
printf("链表初始化成功!\n");
|
||
}
|
||
|
||
// 判断链表L是否为空表
|
||
void Emp(LinkList &L)
|
||
{
|
||
if (L->next == NULL) //todo list 2: 判断头节点的next是否为空
|
||
printf("链表为空表。\n");
|
||
else
|
||
printf("链表为非空表。\n");
|
||
}
|
||
|
||
// 求表长,返回L中数据元素个数
|
||
void Length(LinkList L){
|
||
LNode *p; //申请临时变量p
|
||
p = L->next; //p指向第一个结点(首元结点)
|
||
int length = 0;
|
||
//todo list 3: 遍历单链表,统计结点数
|
||
while (p != NULL) {
|
||
length++;
|
||
p = p->next;
|
||
}
|
||
printf("链表长度为:%d\n", length);
|
||
}
|
||
|
||
// 1、建立递增有序链表:向链表L中插入n个整数,插入时保持链表的有序性(从小到大)。
|
||
void charu_1(LinkList &L, int n)
|
||
{
|
||
LNode *q,*p;
|
||
int i; // 循环变量声明
|
||
for (i = 1; i <= n; i++)
|
||
{
|
||
p = L; //在每次循环开始时,将p指向链表的头节点L
|
||
q = (LinkList)malloc(sizeof(LNode)); //为新的节点分配内存,并将q指向这块内存
|
||
printf("请输入第%d个整数的值:", i);
|
||
scanf("%d", &q->data); //将输入的值存储在q指向的节点的data字段中
|
||
q->next = NULL; //将新节点的next指针设置为NULL,表示新节点当前不指向任何节点。
|
||
|
||
if (p->next == NULL) //如果p的下一个节点是NULL(即链表为空或p指向链表的最后一个节点)
|
||
//todo list 4: 直接插入新节点
|
||
L->next = q;
|
||
else //如果链表不为空或p不是指向链表的最后一个节点,则进入这个else块(查找新节点的插入位置)
|
||
{
|
||
while (p->next != NULL && p->next->data < q->data)
|
||
{
|
||
//todo list 5: p指针不断往后移动
|
||
p = p->next;
|
||
if (p->next == NULL)
|
||
break;
|
||
}
|
||
//todo list 6: 插入*q结点
|
||
q->next = p->next;
|
||
p->next = q;
|
||
}
|
||
}
|
||
printf("数据插入完成!\n");
|
||
}
|
||
|
||
// 显示链表L的所有元素
|
||
void xianshi(LinkList &L)
|
||
{
|
||
LNode *p; //申请临时变量p //LinkList p;
|
||
p = L;
|
||
while (p->next != NULL)
|
||
{
|
||
printf("%4d", p->next->data);
|
||
p = p->next;
|
||
}
|
||
printf("\n");
|
||
}
|
||
|
||
// 2、分解:将链表L中的元素分为奇数和偶数两个链表M和N,并分别显示它们。
|
||
void fenbiao(LinkList &L, LinkList &M, LinkList &N)
|
||
{
|
||
LNode *j,*o,*p;
|
||
p = L->next; //todo list 7: p指针指向第一个数据节点
|
||
|
||
// 初始化M和N链表
|
||
M->next = NULL;
|
||
N->next = NULL;
|
||
|
||
LNode *m_tail = M; // M链表的尾指针
|
||
LNode *n_tail = N; // N链表的尾指针
|
||
|
||
while (p != NULL)
|
||
{
|
||
if (p->data % 2 == 0) //找出偶数元素,用尾插法将这些偶数元素建立成一个【偶数链表】
|
||
{
|
||
o = (LinkList)malloc(sizeof(LNode));
|
||
//todo list 8: 使用尾插法插入偶数节点
|
||
o->data = p->data;
|
||
o->next = NULL;
|
||
n_tail->next = o;
|
||
n_tail = o;
|
||
}
|
||
else //找出奇数元素,用尾插法将这些奇数元素建立成一个【奇数链表】
|
||
{
|
||
j = (LinkList)malloc(sizeof(LNode));
|
||
//todo list 9: 使用尾插法插入奇数节点
|
||
j->data = p->data;
|
||
j->next = NULL;
|
||
m_tail->next = j;
|
||
m_tail = j;
|
||
}
|
||
//todo list 10: p指针往后移动
|
||
p = p->next;
|
||
}
|
||
printf("奇数链表为:");
|
||
xianshi(M);
|
||
printf("偶数链表为:");
|
||
xianshi(N);
|
||
}
|
||
|
||
// 3、合并一个递减链表:将奇数链表J和偶数链表O合并为一个新的链表H,合并时保持元素的有序性。
|
||
void hebiao(LinkList &J, LinkList &O, LinkList &H)
|
||
{
|
||
// 先将两个链表转换为数组,然后排序,最后用头插法创建递减链表
|
||
int data[100]; // 假设最多100个元素
|
||
int count = 0;
|
||
LNode *p;
|
||
int i, j; // 循环变量声明
|
||
LNode *t;
|
||
|
||
// 收集奇数链表的数据
|
||
p = J->next;
|
||
while (p != NULL) {
|
||
data[count++] = p->data;
|
||
p = p->next;
|
||
}
|
||
|
||
// 收集偶数链表的数据
|
||
p = O->next;
|
||
while (p != NULL) {
|
||
data[count++] = p->data;
|
||
p = p->next;
|
||
}
|
||
|
||
// 对数据进行升序排序(从小到大)- 这样头插后会变成降序
|
||
for (i = 0; i < count - 1; i++) {
|
||
for (j = i + 1; j < count; j++) {
|
||
if (data[i] > data[j]) { // 如果前一个元素大于后一个元素,交换它们
|
||
int temp = data[i];
|
||
data[i] = data[j];
|
||
data[j] = temp;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 使用头插法创建递减链表
|
||
H->next = NULL;
|
||
for (i = 0; i < count; i++) {
|
||
t = (LinkList)malloc(sizeof(LNode));
|
||
t->data = data[i];
|
||
t->next = H->next;
|
||
H->next = t;
|
||
}
|
||
|
||
printf("合并后的递减链表为:");
|
||
xianshi(H); //显示合表H
|
||
}
|
||
|
||
int main()
|
||
{
|
||
//生成新结点作为头结点,用头指针分别指向各头结点
|
||
LinkList head = (LinkList)malloc(sizeof(LNode));
|
||
LinkList ji = (LinkList)malloc(sizeof(LNode));
|
||
LinkList ou = (LinkList)malloc(sizeof(LNode));
|
||
LinkList he = (LinkList)malloc(sizeof(LNode));
|
||
|
||
// 初始化链表
|
||
head->next = NULL;
|
||
ji->next = NULL;
|
||
ou->next = NULL;
|
||
he->next = NULL;
|
||
|
||
int choose = -1, n;
|
||
printf("*********************************************\n");
|
||
printf("********** 实验一 *******\n");
|
||
printf("********** 单链表操作 *******\n");
|
||
printf("*********************************************\n");
|
||
printf("********** 1.初始化单链表 *******\n");
|
||
printf("********** 2.建立递增链表 *******\n");
|
||
printf("********** 3.分成奇/偶两链表 *******\n");
|
||
printf("********** 4.合并成递减单链表 *******\n");
|
||
printf("********** 5.显示建立的(递增)单链表整体 *******\n");
|
||
printf("********** 6.求单链表长度 *******\n");
|
||
printf("********** 7.判断链表是否为空 *******\n");
|
||
printf("********** 0.退出程序 *******\n");
|
||
printf("*********************************************\n");
|
||
|
||
while (choose)
|
||
{
|
||
printf("请输入您的选择:");
|
||
scanf("%d", &choose);
|
||
switch (choose)
|
||
{
|
||
case 1:
|
||
chushihua(head, ji, ou, he);
|
||
break;
|
||
case 2:
|
||
printf("请输入要插入的整数个数:");
|
||
scanf("%d", &n);
|
||
charu_1(head, n);
|
||
break;
|
||
case 3:
|
||
fenbiao(head, ji, ou);
|
||
break;
|
||
case 4:
|
||
hebiao(ji, ou, he);
|
||
break;
|
||
case 5:
|
||
printf("当前(递增)单链表内容为:");
|
||
xianshi(head);
|
||
break;
|
||
case 6:
|
||
Length(head);
|
||
break;
|
||
case 7:
|
||
Emp(head);
|
||
break;
|
||
case 0:
|
||
printf("程序已退出,感谢使用!\n");
|
||
exit(0);
|
||
break;
|
||
default:
|
||
printf("输入错误,请重新输入!\n");
|
||
break;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|