单链表的基本操作
背景知识:单链表的插入、删除及应用。
目的要求:
1.掌握单链表的存储特点及其实现。
2.掌握单链表的插入、删除算法及其应用算法的程序实现。
实验内容:
编写一个完整的程序,实现单链表的生成、插入、删除、输出等基本操作。
(1) 随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序)。
(2) 计算单链表的长度,遍历单链表。
(3) 把单链表中的元素逆置(不允许申请新的结点空间)。
(4) 在单链表中删除所有值为偶数的元素结点。
(5) *编写在非递减有序单链表中插入一个元素使链表元素仍有序的函数,并利用该函数
建立一个非递减有序单链表。
(6) * 利用算法 5 建立两个非递减有序单链表,然后合并成一个非递增有序链表。
(7) * 利用算法 5 建立两个非递减有序单链表,然后合并成一个非递减有序链表。
(8) * 利用算法 1 建立的链表,实现将其分解成两个链表,其中一个全部为奇数,另一个
全部为偶数(尽量利用已知的存储空间)。
(9) * 采用单链表实现一元多项式的存储并实现两个多项式相加并输出结果。
(10) 在主函数中设计一个简单的菜单,分别调试上述算法。
代码如下:
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;
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 全部为偶数*/
LinkList.cpp
#include "LinkList.h"
void menu(void)
{
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;
if (Init_Linklist(L)== ERROR)
return ERROR;
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)
{
count ++;
p = p->next;
}
return count;
}
/*单链表逆置*/
void Reverse_Linklist(LinkList L)
{
LinkList p, q ;
p = L->next; // p指向L的首元结点
L->next = NULL;
while(p)
{
q = p->next; //暂存p的下一个节点
p->next = L->next; //p的next指向L的首元结点
L->next = p; // 首元结点指针指向p
p = q; // p指向下一个
}
}
/*删除值为偶数的结点*/
void DelEven_Linklist(LinkList L)
{
LinkList p, q;
q = L;
p = L->next;
while (p)
{
if (p->data % 2 == 0)
{
q->next = p ->next;
delete(p);
p = q->next;
}
else
{
q = p;
p = p->next;
}
}
}
/*在有序单链表中插入元素,链表仍然有序,插入成功返回OK,插入失败返回ERROR*/
Status Insert_Linklist(LinkList L, int x)
{
LinkList p, q, px;
px = (LinkList)malloc(sizeof(Lnode));
if(!px) return ERROR;
px ->data = x;
q = L;
p = L->next;
while (p)
{
if (x > p->data)
{
q = p;
p = p->next;
}
else
{
px->next = p;
q->next = px;
return OK;
}
}
// x大于所有节点的值
px->next = p;
q->next = px;
return OK;
}
/*创建非递减有序单链表,创建成功返回OK,创建失败返回ERROR*/
Status CreatOrder_Linklist(LinkList &L)
{
LinkList p;
int x;
if (Init_Linklist(L)== ERROR)
return ERROR;
printf("输入新链表的节点值,输入-1表示输入结束\n");
while(scanf("%d",&x),x != -1)
{
if (Insert_Linklist(L,x)==ERROR)
return ERROR;
}
return OK;
}
/*两个非递减有序单链表La和Lb合并成一个非递增有序链表Lc*/
void MergeDescend_Linklist(LinkList La, LinkList Lb, LinkList &Lc)
{
LinkList pa, pb, pc,q;
pa = La->next;
pb = Lb->next;
pc = Lc = La;
Lc->next = NULL;
while(pa || pb)
{
if (!pa)
{
q=pb;
pb=pb->next;
}
else if (!pb)
{
q=pa;
pa=pa->next;
}
else if (pa->data <= pb->data)
{
q=pa;
pa = pa->next;
}
else
{
q=pb;
pb = pb->next;
}
q->next = Lc->next; Lc->next = q;
}
delete Lb;
}
/*两个非递减有序单链表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;
Lb = (LinkList)malloc(sizeof(Lnode));
Lb->next = NULL;
q = La;
p = La->next;
while (p)
{
if (p->data % 2 ==1)
{
p = p->next;
q = q->next;
}
else
{
q->next = p->next;
p->next = Lb->next ;
Lb->next = p;
p = q->next;
}
}
}
main.cpp
#include "LinkList.h"
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");
}
} }
运行结果: