单链表的基本操作

一、 实验目的
1.掌握单链表的存储特点及其实现。
2.掌握单链表的插入、删除算法及其应用算法的程序实现。

二、 实验内容及要求
编写一个完整的程序,实现单链表的生成、插入、删除、输出等基本操作。
随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序)。
计算单链表的长度,遍历单链表。
把单链表中的元素逆置(不允许申请新的结点空间)。
在单链表中删除所有值为偶数的元素结点。
编写在非递减有序单链表中插入一个元素使链表元素仍有序的函数,并利用该函数建立一个非递减有序单链表。

  • 利用算法5建立两个非递减有序单链表,然后合并成一个非递增有序链表。
  • 利用算法5建立两个非递减有序单链表,然后合并成一个非递减有序链表。
  • 利用算法1建立的链表,实现将其分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量利用已知的存储空间)。
  • 采用单链表实现一元多项式的存储并实现两个多项式相加并输出结果。
    在主函数中设计一个简单的菜单,分别调试上述算法。
  • 综合训练:
    1)利用链表实现一个班级学生信息管理(数据录入、插入、删除、排序、查找等,并能够实现将数据存储到文件中)
    2)约瑟夫环问题:设有n个人围坐在圆桌周围,从某个位置开始编号为1,2,3,…,n,坐在编号为1的位置上的人从1开始报数,数到m的人便出列;下一个(第m+1个)人又从1开始报数,数到m的人便是第二个出列的人;如此重复下去,直到最后一个人出列为止,得到一个出列的编号顺序。例如,当n=8,m=4时,若从第一个位置数起,则出列的次序为4,8,5,2,1,3,7,6。试编写程序确定出列的顺序。要求用不带头结点的单向循环链表作为存储结构模拟此过程,按照出列顺序打印出个人编号。

DS.h

#ifndef DACM_ZSN_DS_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0

typedef int Status;
#define DACM_ZSN_DS_H
#endif //DACM_ZSN_DS_H

LinkList.h

#ifndef DACM_ZSN_LINKLIST_H

#include "DS.h"

typedef int Elemtype;

typedef struct Node
{
    Elemtype  data;
    struct Node *next;
}Lnode,*LinkList;

void menu();                            /*菜单*/
Status Init_Linklist(LinkList &L);           /*初始化空表*/
Status Creat_Linklist(LinkList &L);         /*尾插法建立单链表*/
void Disp_Linklist(LinkList L);             /*单链表遍历*/
int length_Linklist(LinkList L);             /*计算单链表长度*/
void Reverse_Linklist(LinkList L);         /*单链表逆置*/
void DelEven_Linklist(LinkList L);         /*删除值为偶数的结点*/
Status Insert_Linklist(LinkList L, int x);     /*在有序单链表L中插入元素x,链表仍然有序*/
Status CreatOrder_Linklist(LinkList &L);   /*创建非递减有序单链表*/
void MergeDescend_Linklist(LinkList La, LinkList Lb, LinkList &Lc);  /*两个非递减有序单链表La和Lb合并成一个非递增有序链表Lc*/
void MergeAscend_Linklist(LinkList La, LinkList Lb, LinkList &Lc); /*两个非递减有序单链表La和Lb合并成一个非递减有序链表Lc*/
void Split_Linklist(LinkList La, LinkList &Lb);  /*链表La按值分解成两个链表,La全部为奇数,Lb全部为偶数*/

#define DACM_ZSN_LINKLIST_H

LinkList.cpp

//
// Created by AdministratorYWJ on 2022/3/21.
//
#include "LinkList.h"
#include<iostream>

//插入结点
void Insert_Self(Node *L, int n)//传递头节点指针和将要插入的元素
{
    Node *pre = L;//pre为传递过来的头节点的指针,
    Node *cur = L->next;//cur表示当前位置,这一句很重要,不然插入到最后时链表无法终止

    Node *_new = new Node;
    _new->data = n;//建立新的节点

    while (cur && n > cur->data)//如果链表不为空,且输入的元素比当前元素大
    {
        pre = cur;
        cur = cur->next;//循环得到中断位置的指针
    }

    _new->next = cur;
    pre->next = _new;//将新节点插入中断位置
}


void menu() {
    printf("\t\t\t   单链表基本操作\n\n");
    printf("\t\t\t1.建  立  单  链  表\n");
    printf("\t\t\t2.遍  历  单  链  表\n");
    printf("\t\t\t3.计  算  链 表 长 度\n");
    printf("\t\t\t4.链  表  逆  置\n");
    printf("\t\t\t5.删  除  偶 数 节 点\n");
    printf("\t\t\t6.生 成 值 有 序 单 链 表\n");
    printf("\t\t\t7.合  并 生 成 降  序  链 表\n");
    printf("\t\t\t8.合  并 生 成 升  序  链 表\n");
    printf("\t\t\t9.分  解  链  表\n");
    printf("\t\t\t0.退          出\n\n");
}

/*初始化空表*/
Status Init_Linklist(LinkList &L) {
    L = (LinkList) malloc(sizeof(Lnode));
    if (!L) return ERROR;
    L->next = NULL;
    return OK;
}

/*尾插法建立单链表*/
Status Creat_Linklist(LinkList &L) {
    int x;
    LinkList p, rear;
    Init_Linklist(L);
    rear = L;
    printf("输入-1表示输入结束\n");
    while (scanf("%d", &x), x != -1) {
        p = (LinkList) malloc(sizeof(Lnode));
        if (!p) return ERROR;
        p->data = x;
        rear->next = p;
        rear = p;
    }
    rear->next = NULL;
    return OK;
}

/*单链表遍历*/
void Disp_Linklist(LinkList L) {
    LinkList p;
    p = L->next;
    while (p) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

/*计算单链表长度*/
int length_Linklist(LinkList L) {
    int count = 0;   /*count表示单链表长度*/
    LinkList p;
    p = L->next;
    while (p != NULL) {
        count++;
        p = p->next;
    }
    return count;
}

/*单链表逆置*/
void Reverse_Linklist(LinkList L) {
    LinkList p, q;
    if (L == NULL || L->next == NULL || L->next->next == NULL) //如果单链表为空、只有一个结点,本身就是逆序
        return;
    p = L->next->next;           //将链表的第一个结点给一个指针p,以免丢失数据
    L->next->next = NULL;              //将第一个结点和第二个结点分开
    while (p != NULL)                     //遍历链表
    {
        q = p->next;
        p->next = L->next;
        L->next = p;                   //在头结点的前面插入新的结点
        p = q;                            //为下一次插入做准备
    }
}

/*删除值为偶数的结点*/
void DelEven_Linklist(LinkList L) {
    if (L == NULL)
        return;
    LinkList p, q;
    p = L;
    q = L->next;
    while (q != NULL) {
        if (q->data % 2 == 0) {
            p->next = q->next;
//            free(q);
            q = p->next;
        } else {
            p = q;
            q = q->next;
        }
    }
}


/*在有序单链表中插入元素,链表仍然有序,插入成功返回OK,插入失败返回ERROR*/
Status Insert_Linklist(LinkList L, int x) {

    LinkList p, q;
    p = L;
    q = p->next;
    while (q) {
        if (q->data > x) {
            LinkList s = (LinkList) malloc(sizeof(Lnode));
            s->data = x;
            s->next = q;
            p->next = s;
            return true;
        }
        p = q;
        q = q->next;
    }
    LinkList s = (LinkList) malloc(sizeof(Lnode));
    s->data = x;
    s->next = NULL;
    p->next = s;

    return OK;

}

/*创建非递减有序单链表,创建成功返回OK,创建失败返回ERROR*/
Status CreatOrder_Linklist(LinkList &L) {

//    int value;
//    LinkList s,p,q;
//    L = (LinkList) malloc(sizeof(Lnode));//创建头结点
//    L->next = NULL;
//    scanf("%d", &value);
//    while (value != -1) {
//
//        Insert_Self(L, value);
//        scanf("%d", &value);
//    }
    int x;
    Init_Linklist(L);
    scanf("%d", &x);
    while (x != -1) {
        Insert_Linklist(L, x);
        scanf("%d", &x);
    }
    if (L)
        return OK;
    return ERROR;

}

/*两个非递减有序单链表La和Lb合并成一个非递增有序链表Lc*/
void MergeDescend_Linklist(LinkList La, LinkList Lb, LinkList &Lc) {
    LinkList pa, pb, pc;
    pa = La->next;
    pb = Lb->next;
    pc = Lc = La;
    La->next = NULL;
    while (pa && pb) {
        if (pa->data <= pb->data) {
            pc = pa->next;
            pa->next = Lc->next;     // 每次把小的数插入到Lc的下一位置,类似头插法
            Lc->next = pa;
            pa = pc;
        } else {
            pc = pb->next;
            pb->next = Lc->next;
            Lc->next = pb;
            pb = pc;
        }
    }
    while (pa) {
        pc = pa->next;
        pa->next = Lc->next;//同上插入
        Lc->next = pa;
        pa = pc;
    }
    while (pb) {
        pc = pb->next;
        pb->next = Lc->next;
        Lc->next = pb;
        pb = pc;
    }

}

/*两个非递减有序单链表La和Lb合并成一个非递减有序链表Lc*/
void MergeAscend_Linklist(LinkList La, LinkList Lb, LinkList &Lc) {
    LinkList pa, pb, pc;
    pa = La->next;
    pb = Lb->next;
    pc = Lc = La;
    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;
        }
    }
    pc->next = pa ? pa : pb;
    free(Lb);
}

/*链表La按值分解成两个链表,La全部为奇数,Lb全部为偶数*/
void Split_Linklist(LinkList La, LinkList &Lb) {
    LinkList p, q, b;
    p = La;
    q = p->next;
    b = Lb = La;
    while (q) {
        if (q->data & 1) {//如果是奇数就执行下面的语句
            p=p->next;
            q=q->next;
            continue;
        }
        b->next = q;
        b = q;
        p->next = q->next;
        q = q->next;
    }
//    LinkList Lc;
//    Init_Linklist(Lc);
//    LinkList b_tail = Lb;
//    LinkList c_tail = Lc;
//    LinkList p = La->next;
//    while (p) {
//        La->next = p->next;
//        p->next = NULL;
//        if (p->data % 2 != 0) {
//            b_tail->next = p;
//            b_tail = p;
//        } else {
//            Lc->next = p;
//            Lc = p;
//        }
//        p = La->next;
//    }
//    LinkList s=La->next;
//    La->next=Lc->next;
//    free(s);

}


int main() {
    int choice, length;
    LinkList L, La, Lb, Lc;
    while (1) {
        menu();
        printf("选择你的操作:");
        scanf("%d", &choice);
        switch (choice) {
            case 1:
                if (Creat_Linklist(L))
                    printf("单链表创建成功\n");
                else
                    printf("单链表创建失败\n");
                break;
            case 2:
                Disp_Linklist(L);
                break;
            case 3:
                length = length_Linklist(L);
                printf("单链表长度为:%d\n", length);
                break;
            case 4:
                Reverse_Linklist(L);
                printf("逆置后的链表为:\n");
                Disp_Linklist(L);
                break;
            case 5:
                DelEven_Linklist(L);
                printf("新链表为:\n");
                Disp_Linklist(L);
                break;
            case 6:
                if (CreatOrder_Linklist(L)) {
                    printf("值有序链表为:\n");
                    Disp_Linklist(L);
                } else
                    printf("单链表创建失败\n");
                break;
            case 7:
                CreatOrder_Linklist(La);
                CreatOrder_Linklist(Lb);
                MergeDescend_Linklist(La, Lb, Lc);
                printf("合并后的新链表为:\n");
                Disp_Linklist(Lc);
                break;
            case 8:
                CreatOrder_Linklist(La);
                CreatOrder_Linklist(Lb);
                MergeAscend_Linklist(La, Lb, Lc);
                printf("合并后的新链表为:\n");
                Disp_Linklist(Lc);
                break;
            case 9:
                Creat_Linklist(L);
                Split_Linklist(L, Lb);
                printf("分裂后的新链表为:\n");
                Disp_Linklist(L);
                Disp_Linklist(Lb);
                break;
            case 0:
                return 0;
            default:
                printf("输入错误,请重新输入\n");
        }
    }
}

posted @ 2022-06-30 13:48  WEIWEI1095  阅读(455)  评论(0)    收藏  举报
*/
作品集 //