《软件技术基础》实验指导 实验一
线性表
说明
每个实验题目含有一个main函数和一些函数,与实验题目相关的基本运算的函数定义和main函数定义的代码在附录以及对应的文件夹中给出,供上机实验参考使用。对于每个题目,只需要根据题目要求设计算法,补充函数定义,然后对程序进行编译、调试。
不要在意代码风格
实验一 线性表
一、实验目的
- 熟悉线性表的顺序和链式存储结构
- 掌握线性表的基本运算
- 能够利用线性表的基本运算完成线性表应用的运算
二、实验内容
-
设有一个线性表E={e1, e2, … , en-1, en},设计一个算法,将线性表逆置,即使元素排列次序颠倒过来,成为逆线性表E’={ en , en-1 , … , e2 , e1 },要求逆线性表占用原线性表空间,并且用顺序表和单链表两种方法表示,分别用两个程序来完成。
-
已知由不具有头结点的单链表表示的线性表中,含有三类字符的数据元素(字母、数字和其他字符),试编写算法构造三个以循环链表表示的线性表,使每个表中只含有同一类的字符,且利用原表中的结点空间,头结点可另辟空间。
Tips
-
线性表的逆置,如逆置顺序表,要就地逆置,则首尾对调,直到中间;如逆置单链表,则从头到尾遍历并修改指针域的指向即可,但需主要如何修改指针指向的操作和头结点的处理,具体可以用循环实现或递归实现。
-
建立单链表存放数据元素,分别建立三个循环链表。再进行遍历,将各个元素按照分类插入新的循环链表即可,注意插入循环链表的操作。
Answer
1.1.1
//顺序表逆置的程序代码
#include<stdio.h>
#include<stdlib.h>
//#include<malloc.h>
//顺序表结构类型定义
typedef char datatype;
const int maxsize=1024;
typedef struct
{
datatype data[maxsize];
int last;
}sequenlist;
void create(sequenlist*&);
void print(sequenlist*);
void invert(sequenlist*);
//void main()
int main()
{
sequenlist*L;
create(L);//建立顺序表
print(L);//输出顺序表
invert(L);//调用顺序表逆值的函数
print(L);//输出顺序表
return 0;
}
//建立顺序表
void create(sequenlist*&L)
{
L=(sequenlist*)malloc(sizeof(sequenlist));
L->last=0;
char ch;
while((ch=getchar())!='*')
{
L->last++;
L->data[L->last]=ch;
}
}
//输出顺序表
void print(sequenlist*L)
{
for(int i=1;i<=L->last;i++)
printf("%2c",L->data[i]);
printf("\n");
}
//顺序表逆置
void invert(sequenlist*L)
{
int n=L->last/2;
for(int i=1;i<=n;i++)
{
char temp=L->data[i];
L->data[i]=L->data[L->last-i+1];
L->data[L->last-i+1]=temp;
}
}
1.1.2
//单链表逆置的程序代码
//#include<malloc.h>
#include<stdlib.h>
#include<stdio.h>
//单链表结构类型定义
typedef char datatype;
typedef struct node
{
datatype data;
struct node *next;
}linklist;
void create(linklist*&);
void print(linklist *);
void invert(linklist*);
void invert2(linklist*);
//void main()
int main()
{
linklist*head;
create(head);
print(head);
invert2(head);//调用单链表逆置的函数
print(head);
return 0;
}
//采用尾插法建立具有头结点的单链表
void create(linklist*&head)
{
char ch;
linklist *s,*r;
head=(linklist*)malloc(sizeof(linklist));
r=head;
while((ch=getchar())!='*')
{
s=(linklist*)malloc(sizeof(linklist));
s->data=ch;
r->next=s;
r=s;
}
r->next=NULL;
}
//输出单链表
void print(linklist *head)
{
linklist*p=head->next;
while(p!=NULL)
{
printf("%2c",p->data);
p=p->next;
}
printf("\n");
}
//单链表逆置
//带头结点单链表逆置循环实现
void invert(linklist *head)
{
linklist *p=head->next;//前一结点指针=头结点指针
linklist *q=head->next->next;//当前结点指针=首结点指针
linklist *t=NULL;//下一结点指针=空指针
while(q!=NULL)//当(当前结点指针!=空指针)
{
t=q->next;//下一结点指针=指针域
q->next=p;//指针域=上一节点指针
p=q; //前一结点指针=当前结点指针
q=t;//当前结点指针=下一结点指针
}
head->next->next=NULL;//设置表尾 首结点指针=空指针
head->next=p;//修改表头 头结点指针=前一节点指针
}
//带头结点单链表逆置递归实现
void invert2(linklist *head)
{
linklist* invert2op(linklist*&,linklist*);//操作函数定义 引用头指针 传入首节点指针
linklist* first=head->next;//首节点指针=头结点指针域
invert2op(head,first);//操作函数实现递归
}
//带结点单链表逆置递归实现操作函数
linklist* invert2op(linklist*&head,linklist *first)
{
linklist *p=first;//操作指针=首节点
if(p==NULL)//如果是空链表
return NULL;//返回空
linklist *q=p->next;//下一结点指针=操作指针指针域
if(q==NULL)//下一结点指针空即如果只剩一个节点
return p;//返回当前节点
else
first=invert2op(head,q);//首节点指针=操作函数返回
q->next=p;//下一结点指针域=操作指针
p->next=NULL;//操作指挥指针域置空
head->next=first;//头结点指针域=首节点
return first;//操作函数返回 首节点指针
}
1.2
#include<stdio.h>
//#include<malloc.h>
#include<stdlib.h>
//链表结构类型定义
typedef char datatype;
typedef struct node
{
datatype data;
struct node *next;
}linklist;
void create(linklist*&);
void resolve(linklist*,linklist*,linklist*,linklist*);
void insert(linklist*,linklist*);
void print1(linklist*);
void print2(linklist*);
//void main()
int main()
{
linklist*head,*letter,*digit,*other;
create(head);
print1(head);
letter=(linklist*)malloc(sizeof(linklist));//建立3个空循环链表
letter->next=letter;
digit=(linklist*)malloc(sizeof(linklist));
digit->next=digit;
other=(linklist*)malloc(sizeof(linklist));
other->next=other;
resolve(head,letter,digit,other);//调用分解单链表的函数
print2(letter);//输出循环链表
print2(digit);
print2(other);
return 0;
}
//建立单链表
void create(linklist *&head)
{
datatype x;
linklist *s, *r;
// head=(linklist*)malloc(sizeof(linklist));
head=new linklist;
r=head;
while((x=getchar())!='$')
{
s=(linklist*)malloc(sizeof(linklist));
s->data=x;
r->next=s;
r=s;
}
r->next=NULL;
}
//在循环链表中插入
void insert(linklist*h,linklist*p)//首结点指针 插入指针指向插入结点
{
linklist *q=h;//操作指针=头结点
while(q->next!=h)//当(操作指针所指向的结点指针域!=头结点)
q=q->next;//操作指针=操作指针做指向的结点指针域
q->next=p;//操作指针所指向的结点指针域=插入结点
p->next=h;//插入结点的指针域=首结点
}
//输出单链表
void print1(linklist *head)
{
linklist *p=head->next;
while(p!=NULL)
{
printf("%c",p->data);
p=p->next;
}
printf("\n");
}
//输出循环链表
void print2(linklist*head)
{
linklist *p=head->next;
while(p!=head)
{
printf("%c",p->data);
p=p->next;
}
printf("\n");
}
//按字母、数字、其它字符分解单链表
void resolve(linklist*head,linklist*letter,linklist*digit,linklist*other)
{
linklist *p=head->next;//操作指针=首结点
while(p!=NULL)//当(操作指针!=空指针)
{
linklist *q=p->next;//缓存指针=操作指针的下一结点
if(((p->data>='A')&&(p->data<='Z'))||((p->data>='a')&&(p->data<='z')))//如果是字母
insert(letter,p);//将操作指针指向的结点插入letter链表
else if((p->data>='0')&&(p->data<='9'))
insert(digit,p);
else
insert(other,p);
p=q;//操作指针=缓存指针
}
}