2.1 实验1 线性表应用二、单向链表

目的要求
1.掌握单链表的存储特点及其实现。
2.掌握单链表的插入与删除算法的程序实现。
实验内容
1.随机产生或键盘输入一组元素(不少于10个元素),建立一个带头结点的单链表。
2.把单链表中的元素逆置(不允许申请新的结点空间)。
3.删除单链表中所有的偶数元素结点。
4.编写在非递减有序链表中插入一个元素使链表元素仍有序的函数,利用该函数建立一个
非递减有序单链表。
5.利用算法4建立两个非递减有序单链表,然后合并成一个非递增链表。
6.把算法1建立的链表分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量
利用已有存储空间)。
7.在主函数中设计一个简单菜单,调用上述算法。
实验说明
1.结点类型定义
typedef int ElemType; // 元素类型
typedef struct LNode
{
ElemType data ;
struct LNode * next ;
} LNode, *pLinkList ;
2.为了简单,采用带头结点的单链表。

LinkList.h

#include <stdlib.h>
#include <stdio.h>
typedef  int  ElemType; // 元素类型 
typedef struct Lnode
{
    ElemType data;
    struct Lnode* next;
}LNode, * LinkList;
void menu();//菜单
void init(LinkList& L);//创建带头节点的单向链表
void insertHead(LinkList& L, int m);//输入一组数,头插法
void insertTail(LinkList& L, int m);//输入一组数,尾插法
void print(LinkList& L);//显示单向链表
void contrary(LinkList& L);//逆置元素(不申请新节点)
void delet(LinkList& L);//删除所有值为偶数的节点
void insertOrderly(LinkList& L, int c);//递增数列中插入元素仍有序
LinkList inde(LinkList& L, LinkList& J);//建立两个递增的有序单向链表,合并成一个递减(建立两个递增的有序单向链表,合并成一个递增,再就地逆置元素)
void spilt(LNode* L, LNode* B);//把算法1建立的链表分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量利用已有存储空间)。
    
#pragma once

LinkList.cpp

#include"LinkList.h"
//创建带头节点的单向链表
void init(LinkList& L)
{
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
}

//输入一组数,头插法
void insertHead(LinkList& L, int m)
{
    LinkList p;
    p = (LinkList)malloc(sizeof(LNode));
    p->data = m;
    p->next = L->next;
    L->next = p;
}

//输入一组数,尾插法
void insertTail(LinkList& L, int m)
{
    LinkList p, q;
    p = (LinkList)malloc(sizeof(LNode));
    p->data = m;
    p->next = NULL;
    q = L;
    if (L == NULL) //首节点为空
    {
        L = p;  //L指向p
        p->next = NULL;
    }
    else {
        while (q->next != NULL)
        {
            q = q->next;//到尾巴时
        }
        q->next = p; //插入结点
    }

}

//显示单向链表
void print(LinkList& L)
{
    LinkList p;
    p = (LinkList)malloc(sizeof(LNode));
    p = L->next;
    while (p)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

//逆置元素(不申请新节点)
void contrary(LinkList& L) {
    LinkList p, q;
    p = (LinkList)malloc(sizeof(LNode));
    q = (LinkList)malloc(sizeof(LNode));
    p = L->next;
    L->next = NULL;//将链断开
    while (p) {
        q = p->next;//q永远在p的后一个
        p->next = L->next;//将p连在L的后面,先把尾巴连上
        L->next = p;//将p连在L的后面,再把前面接上
        p = q;//p指向下一个,即q所在的位置
    }
}

    //删除所有值为偶数的节点
    void delet(LinkList & L)
    {
        LinkList p, q;
        p = (LinkList)malloc(sizeof(LNode));
        q = (LinkList)malloc(sizeof(LNode));
        p = L->next;
        q = L;
        while (p)
        {
            if ((p->data) % 2 != 0)
            {
                p = p->next;
                q = q->next;
            }
            else {
                q->next = p->next;//删除节点
                p = p->next;
            }
        }
    }

    //递增数列中插入元素仍有序
    void insertOrderly(LinkList& L, int c)
    {
        LinkList p, q, s;
        s = (LinkList)malloc(sizeof(LNode));
        p = (LinkList)malloc(sizeof(LNode));
        q = (LinkList)malloc(sizeof(LNode));
        p = L->next;
        q = L;
        s->data = c;
        while ((p->data <= c) && (p->next != NULL))//条件是p->next!=null
        {
            p = p->next;
            q = q->next;
        }
        if (p->next == NULL)//特殊考虑p指向结尾
        {
            p->next = s;
            s->next = NULL;
        }
        else {
            s->next = p;
            q->next = s;
        }

    }
    //建立两个递增的有序单向链表,合并成一个递减(建立两个递增的有序单向链表,合并成一个递增,再就地逆置元素)

    LinkList inde(LinkList& L, LinkList& J)
    {

        LinkList Q;
        init(Q);
        LinkList pa, pb, pc;
        pa = (LinkList)malloc(sizeof(LNode));
        pb = (LinkList)malloc(sizeof(LNode));
        pc = (LinkList)malloc(sizeof(LNode));
        pa = L->next;
        pb = J->next;
        pc = Q;
        pc->next = NULL;
        while (pa && pb)
        {
            if (pa->data <= pb->data)
            {
                pc->next = pa;
                pc = pa;
                pa = pa->next;
            }
            else {
                pc->next = pb;
                pc = pb;
                pb = pb->next;
            }
        }
        if (pa)
        {
            pc->next = pa;
        }
        else
        {
            pc->next = pb;
        }
        free(L);
        free(J);

        return Q;
    }
    //把算法1建立的链表分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量利用已有存储空间)。
    void spilt(LNode* L, LNode* B) {
        LNode* p = L;
      
        LNode* q = B;
        LNode* r;
        while (p->next != NULL) {
            if (p->next->data % 2 == 0) {
                //下面处理的是取下链表中的偶数节点插入到链表中 
                //偶数的时候取出来插入到链表B中 
                r = p->next;
                p->next = p->next->next;
                //q指针向下移动
                q->next = r;
                r->next = NULL;
                q = q->next;

            }
            else {
                p = p->next;
            }
            printf("\n");
        }
        //输出链表A的内容 
        LNode* s = L;
        while (s->next != NULL) {
            printf("%d ", s->next->data);
            s = s->next;
        }

        printf("\n");
        //输出链表B的内容 
        s = B;
        while (s->next != NULL) {
            printf("%d ", s->next->data);
            s = s->next;
        }
    }

    void menu() {
        printf("单向链表基本操作\n");
        printf("1.建立带头节点的单链表\n");
        printf("2.单链表元素逆置\n");
        printf("3.删除单链表中所有的偶数元素结点\n");
        printf("4.插入一个元素使链表元素仍有序\n");
        printf("5.建立两个非递减有序单链表,然后合并成一个非递增链表\n");
        printf("6.把1建立的链表分解成两个链表,其中一个全部为奇数,另一个全部为偶数\n");
        printf("0.退出\n\n");
    }

main.cpp

#include"LinkList.h"
int main()
{
	int choice;
	LinkList S;
	int number, data;
	LNode* head;
	init(S);//创建带头节点的链表
	LNode* B;
	B = (LNode*)malloc(sizeof(LNode));
	B->next = NULL;
	while (1)
	{
		menu();
		printf("选择你的操作:");
		scanf_s("%d", &choice);
		switch (choice)
		{
		case 1:
			printf("输入插入元素的个数\n");
			scanf_s("%d", &number);//输入插入元素的个数
			for (int i = 0; i < number; i++)
			{
				printf("尾插法,依次输入元素,以回车分隔,输入元素第%d个\n", i + 1);
				scanf_s("%d", &data);
				//insertHead(S,data);//头插法,输入元素
				insertTail(S, data);//尾插法,输入元素
			}
			print(S);
			break;
		case 2:
			contrary(S);
			print(S);
			break;
		case 3:
			delet(S);
			print(S);
			break;
		case 4:
			printf("输入要插入的元素\n");
			int k;
			scanf_s("%d", &k);//要插入递增数列的k
			insertOrderly(S, k);//递增数列中插入元素仍有序
			print(S);// 显示单向链表
			break;
		case 5:
			LinkList V, W, Res;
			int m, n;
			init(V);//创建带头节点的链表
			init(W);//创建带头节点的链表
			printf("输入两个链表的元素个数分别为m,n\n");
			scanf_s("%d%d", &m, &n);//输入插入元素的个数
			printf("请输入第一个链表的元素\n");
			for (int i = 0; i < m; i++)
			{
				printf("尾插法,依次输入有序递增元素,以回车分隔,输入元素第%d个\n", i + 1);
				scanf_s("%d", &data);
				//insertHead(U,data);//头插法,输入元素
				insertTail(V, data);//尾插法,输入元素
			}
			printf("请输入第二个链表的元素\n");
			for (int i = 0; i < n; i++)
			{
				printf("尾插法,依次输入有序递增元素,以回车分隔,输入元素第%d个\n", i + 1);
				scanf_s("%d", &data);
				//insertHead(U,data);//头插法,输入元素
				insertTail(W, data);//尾插法,输入元素
			}
			Res = inde(V, W);//6.建立两个递增的有序单向链表,合并成一个递减
			contrary(Res);//3.逆置元素(不申请新节点)
			print(Res);// 2.显示单向链表

			break;

		case 6:
      spilt(S, B);
			break;
		/*case 0:
			return 0;
		default:
			printf("输入错误,请重新输入\n");*/
		}
	}
}

vs2019运行成功
运行截图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值