实验二 链表

数据结构实验报告

  1. 问题描述及分析

问题描述

2-23设计循环单链表。要求:

(1)循环单链表的操作,包括初始化,求数据元素个数,插入、删除、取数据元素。
(2)设计一个测试主函数实际运行验证所设计循环单链表的正确性。

分析:首先建立一个循环单链表软工具箱,然后根据题目要求,能够在循环单链表的任意位置插入、删除结点以及确定某一元素在链表中的位置。

  1. 建立循环单链表功能

建立一个带头结点的循环单链表,确定DataType与Node。

  1. 初始化

将带头结点的循环单链表初始化。

  1. 插入功能

输入的形式:在带头节点的单链表head的第i个(0~size)个结点前插入一个存放元素x的结点,首先要在单链表中找到ai-1结点并由指针p指示,然后动态申请一个内存单元并由指针q指示,并把元素x的值赋予新的结点的数据域(即q->data=x),最后修改新的结点的指针指向ai的结点(q->next=p->next),并修改ai-1结点的指针域使之指向新结点q(即p->next=q).

循环条件:子条件p->next!=head保证指针所指结点存在,子条件j<i-1保证最终让指针p指向ai-1结点

输出的形式:如果输入的参数不合法,则显示参数错误信息。

返回值:插入成功返回1,插入失败返回0。

  1. 删除功能

输入的形式:要在带头结点的单链表中删除ai结点,首先要在单链表中寻找到ai-1结点并由指针p指示,然后让指针s指向ai结点(s=p->next),并把ai结点数据域赋予元素x(*x=s->data),最后把ai结点脱链(p->next=p->next->next),并动态释放ai结点的内存单元(free(s)).

循环条件:p->next!=head保证ai-1存在;p->next->next!=head保证ai结点存在;j<i-1保证最终让指针p指向ai-1结点。

输出的形式:如果输入的参数不合法或顺序表为空,则显示参数错误信息。

返回值:删除成功返回1,删除失败返回0。

  1. 查找功能

输入的形式:取元素函数和删除函数基本类同,但取元素函数的循环条件改为j<i,并且不删除ai结点

输出的形式:如果输入的参数不合法,则显示参数错误信息。

返回值:查找成功返回1,查找失败返回0。

2.概要设计

(1)为了实现上述程序功能,先定义一个简化的包含抽象数据类型的头文件

typedef int DataType;

typedef struct Node

{

DataType data;

struct Node *next;

}SLNode;

void ListInitiate(SLNode **head);//初始化

int ListLength(SLNode *head);//求当前元素个数

int ListInsert(SLNode *head,int i,DataType x);//插入

int ListDete(SLNode *head,int i,DataType *x);//删除

int ListGet(SLNode *head, int i,DataType *x);//取元素

void Destroy(SLNode **head);//撤销

(2)程序包含的模块

主函数main()

初始化函数 ListInitiate(SLNode **head);

插入元素函数ListInsert(SLNode *head,int i,DataType x);

删除元素函数ListDelete(SLNode *head,int i,DataType *x);

提取元素函数ListGet(SLNode *head, int i,DataType *x);

当前元素个数函数ListLength(SLNode *head);

(3)主函数的伪码

main(){

定义一个单链表SLNode;

初始化SLNode;

建立SLNode;

删除某一元素;

循环以下处理,直至结束:

{

取顺序表元素并输出;

}

}

3.详细设计

结合概要设计中定义的包含抽象类型的头文件,进行数据结构设计和算法设计。

  1. 数据结构

链表中的结点的结构体定义如下:

typedef int DataType;

typedef struct Node

{

DataType data;

struct Node *next;

}SLNode;
  1. 基本操作的伪码算法

初始化循环单链表

void ListInitiate(SLNode **head){  //初始化

*head=(SLNode *)malloc(sizeof(SLNode));//申请头结点,由head指示其地址

(*head) ->next=*head;//置结束标记*head

}

返回当前元素个数

int ListLength(SLNode *head){ //求当前元素个数

SLNode *p =head; //p指向头结点

int size =0; //size初始为0

while(p->next !=head)//循环计数

{

p=p->next;

size++;

}

return size;

}

插入元素

int ListInsert(SLNode *head,int i,DataType x){

//在带头结点的单链表head的第i(0<=i<=size)个结点前插入存放一个数据元素x的结点

//插入成功则返回1,失败则返回0

SLNode *p,*q;

int j;

p=head;

j=-1;

while(p->next!=head&&j<i-1)

//最终让指针p指向第i-1个结点

{

p=p->next;

j++;

}

if(j!=i-1)

{

printf("插入元素位置参数错!");

return 0;

}

q=(SLNode *)malloc(sizeof(SLNode));//生成新结点

q->data =x; //新结点数据域赋值

q->next =p->next; //插入步骤1

p->next =q; //插入步骤2

return 1;

}

删除元素

Int ListDelete(SLNode *head, int i,DataType *x){

//删除带头结点单链表head的第i(0<=i<=size-1)个结点

//被删除结点的数据域值由x带回,删除成功则返回1,失败则返回0

SLNode *p,*s;

int j;

p=head;

j=-1;

while(p->next !=head && p->next->next!=head &&j<i-1){

//循环结束时指针p指向第i-1个结点

p=p->next;

j++;

}

if(j!=i-1)

{

printf(“删除元素位置参数错!”);

return 0;

}

s=p->next;//指针s指向ai结点

*x=s->data;//把指针s所指的结点的数据域赋值给x

p->next = p->next->next;//删除

free(s);//释放指针s所指结点的内存空间

return 1;

}

取元素

Int ListGet(SLNode *head, int i,DataType *x){

SLNode *p;

int j;

p=head;

j=-1;

while(p->next!=head&&j<i)

{

p=p->next;

j++;

}

if(j!=i)

{

printf(“取元素位置参数错!”);

return 0;

}

*x =p->data;

return 1;

}

撤销

void Destroy(SLNode **head){

SLNode *p,*p1;

p=*head;

While(p!=NULL)

{

p1=p;

p=p->next;

free(p1);

}

*head=NULL;

}

主程序:

#include<stdio.h>//包含printf()函数

#include<malloc.h>//包含malloc()函数

#include"LinList.h"//包含LinList.h头文件

typedef int DataType;//包含DataType为int

typedef struct Node

{

DataType data;

struct Node *next;

}SLNode;

int ListDelete(Node *head,int i, DataType x);

int ListGet (Node *head, int i, DataType *x);

int ListInsert(Node *head, int i, DataType x);

void print(Node *head);

Node *ListInitiate();

void main (void)

{

int i=4;

Node *p;

p=ListInitiate();

print(p);

ListLength(p);

printf("链表长度:\n");

printf("%d  \n",ListLength(p));

{

ListInsert(p,i,i+1);

printf("插入一个元素后:\n");

print(p);

ListDelete(p,i, i+1);

printf("删y插入元素后:\n");

print(p);

}

{

ListDelete(p,i, i+1);

printf("删除一个元素后:\n");

print(p);

}

}

Node *ListInitiate() //创建单链表返回一个指向链表表头结点的指针head

{

Node *head,*q,*p; //定义指针变量

int a,n;

printf("输入链表长度n:\n");        //链表大小为n

scanf("%d",&n);

head=(Node *)malloc(sizeof(Node));//申请新的存储空间,建立表头结点

head->data=n;

q=head;

while(n>0)

{

scanf("%d",&a); //输入链表元素

p=(Node*)malloc(sizeof(Node));

p->data=a;

q->next=p;

q=p;

n=n-1;

}

q->next=NULL;

return(head); //返回表头指针head}

void print(Node *head) //输出单链表各个元素

{

Node *p;

p=head->next;

while(p!=NULL)

{

printf("%   d",p->data);

p=p->next;

}

printf("\n");

}

int ListLength(Node *head)//测元素个数

{

Node *p=head;

int size=0;

while(p->next!=NULL)

{

p=p->next;

size++;

}

return size;

}

int ListInsert(Node *head, int i, DataType x)//插入元素

{

Node *p,*q;

int j;

p=head;

j=-1;

while(p->next!=NULL && j<i-1)//最终让指针p指向第i-1个位置

{

p=p->next;

j++;

}

if(j!=i-1)

{

printf("插入元素位置参数错误!\n");

return 0;

}



q=(Node *)malloc(sizeof(Node));//生成新结点

q->data=x;//新结点数据域赋值

q->next=p->next;

p->next=q;

return 1;

}

int ListDelete(Node *head,int i, DataType x)

{

Node *p,*s;

int j;

p=head;

j=-1;

while(p->next!=NULL && p->next->next!=NULL && j<i-1)//循环结束时指针p指向第i-1个位置

{

p=p->next;

j++;

}

if(j!=i-1)

{

printf("删除元素位置参数错误!\n");

return 0;

}

s=p->next;//指针s指向ai结点

x=s->data;//把s所指结点数据域值赋给x

p->next=p->next->next;//删除

free(s);//释放指针s所指结点的内存空间

return 1;

}

int ListGet (Node *head, int i, DataType *x)//取元素

{

Node *p;

int j;

p=head;

j=-1;

while(p->next!=NULL&&j<i)

{

p=p->next;

j++;

}

if(j!=i){

printf("取元素位置参数错误!\n");

return 0;

}

*x=p->data;

return 1;

}

}

5.调试与分析

 

该结果与预期结果一致,说明所设计的单循环链表是正确的。

  1. 总结

书中已经给出初始化、查找、插入、删除等函数代码,但做完后大大加深了自己对书中各个知识点的印象和理解,也学会了一写编写算法的小技巧,要有耐心,多看书多实践,做数据结构上机实验感觉困难重重,有很多不懂的地方,由于以前C语言学得不是很扎实,所以在编写程序时候遇到很多问题,很多地方是照着课本上的源程序复制下来的,不知其原理。多亏有班上这方面学得好的同学的悉心指导才得以把程序做出来,当然,通过这个实验也学到很多东西,

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

popywei

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值