一、 目的
1.掌握单链表的存储特点及其实现。
2.掌握单链表的插入、删除算法及其应用算法的程序实现。
二、内容
1、内容
编写一个完整的程序,实现单链表的生成、插入、删除、输出等基本操作。
(1) 随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序)。
(2) 计算单链表的长度,遍历单链表。
(3) 把单链表中的元素逆置(不允许申请新的结点空间)。
(4) 在单链表中删除所有值为偶数的元素结点。
(5) 编写在非递减有序单链表中插入一个元素使链表元素仍有序的函数,并利用该函数建立一个非递减有序单链表。
(6) *利用算法5建立两个非递减有序单链表,然后合并成一个非递增有序链表。
(7) *利用算法5建立两个非递减有序单链表,然后合并成一个非递减有序链表。
(8) *利用算法1建立的链表,实现将其分解成两个链表,其中一个全部为奇数,另一个全部为偶数(尽量利用已知的存储空间)。
(9) *采用单链表实现一元多项式的存储并实现两个多项式相加并输出结果。
(10) 在主函数中设计一个简单的菜单,分别调试上述算法。
(11) *综合训练:
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。试编写程序确定出列的顺序。要求用不带头结点的单向循环链表作为存储结构模拟此过程,按照出列顺序打印出个人编号。
2、主要数据类型与变量
1.类型定义
typedef int ElemType; //元素类型
typedef struct node
{
ElemType data;
struct node *next;
}LinkNode, *LinkList;
2.为了算法实现简单,建议采用带头结点的单链表。
3、算法思想描述
声明好数据结构的类型,开始编写代码,先声明一个结点,置为头结点(本中所有链表均有头结点),插入数据时,声明一个节点,数据域存放数据,原链表尾部结点指针域存放当前结点地址,弄好无序的链表,通过比较,使用头插法,将无序链表置为有序链表,遍历节点,当结点数据域为偶数时,将前面节点指针域存放需要删除节点的指针域数据,然后完成删除偶数结点。
三、系统测试。
2、测试结果
1. 创建单链表
2. 遍历单链表
3. 计算单链表长度
4. 链表逆置
5. 删 除 值为偶 数 节 点
6.生成有序单链表
7.合 并生成降 序 链表
8.合 并生成升 序 链 表
9.分解链表
附:程序源代码
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"
typedefint Elemtype;
typedefstruct Node
{
Elemtype data;
struct Node *next;
}Lnode,*LinkList;
voidmenu(); /*菜单*/
StatusInit_Linklist(LinkList &L); /*初始化空表*/
StatusCreat_Linklist(LinkList &L); /*尾插法建立单链表*/
voidDisp_Linklist(LinkList L); /*单链表遍历*/
intlength_Linklist(LinkList L); /*计算单链表长度*/
voidReverse_Linklist(LinkList L); /*单链表逆置*/
voidDelEven_Linklist(LinkList L); /*删除值为偶数的结点*/
StatusInsert_Linklist(LinkList L, int x); /*在有序单链表L中插入元素x,链表仍然有序*/
StatusCreatOrder_Linklist(LinkList &L); /*创建非递减有序单链表*/
voidMergeDescend_Linklist(LinkList La, LinkList Lb, LinkList &Lc); /*两个非递减有序单链表La和Lb合并成一个非递增有序链表Lc*/
voidMergeAscend_Linklist(LinkList La, LinkList Lb, LinkList &Lc); /*两个非递减有序单链表La和Lb合并成一个非递减有序链表Lc*/
voidSplit_Linklist(LinkList La, LinkList &Lb); /*链表La按值分解成两个链表,La全部为奇数,Lb全部为偶数*/
LinkList.cpp
#include "LinkList.h"
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;
LinkList p;
p = L->next;
while(p)
{
count++;
p = p->next;
}
return count;
}
void Reverse_Linklist(LinkList L)
//单链表逆置
{
LinkList p,q;
p = L->next;
L->next = NULL;
if(L != NULL){
while(p){
q = p;
p= p->next;
q->next =L->next;
L->next = q;
}
}else{
printf("链表为空");
}
}
void DelEven_Linklist(LinkList L)
//删除值为偶数的结点
{
LinkList p,q;
p = L;
q = p->next;
while(q){
if(!(q->data&1)){
if(q->next == NULL){
p->next=NULL;
free(q);
}else{
q = q->next;
p->next =p->next->next;
}
}else{
q = q->next;
p = p->next;
}
}
}
Status Insert_Linklist(LinkList L, int x)
//在有序单链表中插入元素,链表仍然有序
{
LinkList p,q,r;//r为携带x的新结点
int flag=0;
r=(LinkList)malloc(sizeof(Lnode));
r->data = x;
if(L->next != NULL){
p=L;
q=p->next;
while(q){
if((r->data) <(q->data)){
flag=1;
r->next =p->next;
p->next = r;
break;
}else{
q=q->next;
p=p->next;
}
}
if(flag==0 &&p->next==NULL){
p->next=r;
r->next=NULL;
}
}else{
r->next=L->next;
L->next=r;
}
//free(r);
return OK;
}
Status CreatOrder_Linklist(LinkList &L)
//创建非递减有序单链表
{
int x;
Init_Linklist(L);
printf("请输入表中元素值,以-1结束\n");
while(scanf("%d",&x), x != -1)
Insert_Linklist(L, x);
return OK;
}
void MergeDescend_Linklist(LinkList La, LinkList Lb, LinkList &Lc)
//两个非递减有序单链表合并成一个非递增有序链表
{
LinkList pa, pb, pc,p;
pa = La->next;
pb = Lb->next;
pc = Lc = La;
pc->next=NULL;
while(pa || pb){
if(!pa){
p=pb;
pb=pb->next;
}else if(!pb){
p=pa;
pa=pa->next;
}else if(pa->data <=pb->data){ //用头插法
p=pa;
pa=pa->next;
}else{
p=pb;
pb=pb->next;
}
p->next=pc->next;
pc->next=p;
}
free(Lb);
}
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);
}
void Split_Linklist(LinkList La, LinkList &Lb)
//链表按值分解成两个链表,一个全部为奇数,另一个全部为偶数
{
LinkList p, q,r;
Lb=(LinkList)malloc(sizeof(Lnode));
Lb->next=NULL;
r=Lb;
p=La;
q=La->next;
while(q){
if(!(q->data&1)){
q=q->next;
r->next=p->next;
p->next=r->next->next;
r->next->next=NULL;
r=r->next;
}else{
q=q->next;
p=p->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:
exit(-1);
default:
printf("输入错误,请重新输入\n");
menu();
}
}
return 0;
}