数据结构实验指导
实验一:线性表的操作
实验一A:线性表的顺序存储结构操作
【题目】
设顺序表Va中的数据元素递增有序,试写一算法,将x插入到顺序表的适当位置上,以保证该表的有序性。
【实验目的】
掌握用动态数组实现线性表的顺序存储结构及顺序表的初始化、查找、插入操作。
【分析】
本程序设计方法:先根据插入结点x的值查找插入位置,然后从表尾到插入位置的元素依次往后移一步空出x元素的位置,送入x,顺序表长度增1。
【程序】
#include<stdio.h>
#include<stdlib.h>
#define list_init_size 10
#define increment 3
typedef struct {
int *elem;
int length,listsize;
}sqlist; //类型定义
int *p;
void initlist_sq(sqlist &L) //初始化顺序表
{
L.elem=(int *)malloc(list_init_size*sizeof(int));
if(!L.elem) printf("overflow");
else {L.length=0;
L.listsize=list_init_size;
}
}
void output(sqlist L) //输出顺序表
{ for(p=L.elem;p<=L.elem+L.length-1;p++)
printf(" %d",*p);
}
void ex2_11(sqlist &L,int x) //顺序表中插入x
{ int *q;
if (L.length>=L.listsize) //判表是否满
{L.elem=(int *)realloc(L.elem,
(L.listsize+increment)*sizeof(int));
L.listsize+=increment;
}
p=L.elem;
while (*p<x && p<=L.elem+L.length-1) //查找插入位置
p++;
for(q=&(L.elem[L.length-1]);q>=p;q--) //元素后移空出插入位置
*(q+1)=*q;
*p=x;
++L.length;
}
void main()
{sqlist L;int i=0,x;
initlist_sq(L);
printf("\n输入顺序表的长度:");
scanf("%d",&L.length);
p=L.elem;
printf("\n输入顺序表各元素:");
for(;i<L.length;i++)
scanf("%d",p++);
output(L);
printf("\n输入x=");
scanf("%d",&x);
ex2_11(L,x);
printf("\n结果是:");
output(L);
printf("\n");
}
【运行结果】
图1顺序表中插入x运行界面
实验一B:线性表的链式存储结构操作
【实验目的】
掌握用单链表的创建、打印、查找、插入、删除等基本操作和它们的综合操作。
【实验一B题目1】
已知线性表中的元素以值递增有序排列,并以单链表作存储结构。试写一高效的算法,删除表中所有值大于mink且小于maxk的元素(若表中存在这样的元素)同时释放被删除结点空间。
【分析】
算法先从首结点开始查找,找到大于mink的结点停下,再判断是否小于maxk,若是则删除,重复这样的判断,直至不小于maxk为止;若不是则结束。此算法由下面程序中的EX2_19函数实现。
【实验一B题目2】
试写一算法,对单链表实现就地逆置。
【分析】
逆置的方法是改变每个结点中的指针,使其指向前驱,算法中用p当前结点,q指向p的前驱,r指向p的后继,p->next=q则当前结点的指针指向前驱了,然后三根指针同步往后移直至所有结点处理完。此算法由下面程序中的ex2_22函数实现。
【实验一B题目3】
假设有两个按元素值递增有序排列的线性表A和B,均以单链表作存储结构,请编写算法将A和B表归并成一个按元素值递减有序(即非递增有序,允许表中含有值相同的元素)排列的线性表C,并要求利用表(即A表和B表)的结点空间构造C表。
【分析】
反复进行两表的比较,将元素值小的结点插入到 C表的首端,直至两表的元素都插入完。此算法由下面程序中的ex2_24函数实现。
【程序】
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
int data;
struct node *next;
}lnode,*linklist;
linklist creat() //创建带头单链表
{linklist p,head;int x;
head=(linklist)malloc(sizeof(lnode));
p=head;
scanf("%d",&x);
while (x>0)
{p->next=(linklist)malloc(sizeof(lnode));
p=p->next,p->data=x;scanf("%d",&x);
}
p->next=NULL;
return head;
}
void out(linklist head) //输出单链表
{linklist p;
for(p=head->next;p;p=p->next)
printf("%3d",p->data);
}
void ex2_19(linklist l,int mink,int maxk) //删除mink~maxk函数
{linklist p,q;
if (mink<maxk)
{p=l;
while (p->next && p->next->data<=mink) //查找开始位置
p=p->next;
while (p->next && p->next->data<maxk) //判断、删除
{q=p->next;p->next=q->next;free(q);}
}
}
void ex2_22(linklist L) //逆置单链表
{linklist p,q,r;
q=NULL;p=L->next;
while (p)
{r=p->next;
p->next=q;
q=p;p=r;
}
L->next=q;
}
linklist ex2_24(linklist A,linklist B)
//两个递增有序链表合并成一个递减有序的单链表
{linklist C,p,q,r;
C=A;p=A->next;q=B->next;C->next=NULL;
while (p&&q)
{if (p->data==q->data)
{r=q;q=q->next;free(r);}
else {if(p->data<q->data)
{ r=p;p=p->next;}
else {r=q;q=q->next;}
r->next=C->next;C->next=r;
}
}
while (p)
{ r=p;p=p->next;
r->next=C->next;C->next=r;
}
while (q)
{ r=q;q=q->next;
r->next=C->next;C->next=r;
}
return C;
}
void main()
{linklist HL,HL2;int n,m;
printf("\n创建2-19的单链表:\n输入链表的有序数据(用0表示输入结束):");
HL=creat();
printf("2_19的单链表为: ");
out(HL);
printf("\n输入 mink,maxk");
scanf("%d,%d",&n,&m);
ex2_19(HL,n,m);
printf("2_19的结果是:");
out(HL);
printf("\n运行2_22:");
ex2_22(HL);
printf("\n2_22的结果是:");
out(HL);
printf("\n创建2_24的单链表A:\n输入链表的有序数据(用0表示输入结束):");
HL=creat();
printf("\n创建2_24的单链表B:\n输入链表的有序数据(用0表示输入结束):");
HL2=creat();
HL=ex2_24(HL,HL2);
printf("2_24的结果是:");
out(HL);
printf("\n");
}
【运行结果】
图2实验一B单链表操作运行界面
实验二 栈和队列的操作
实验二A 链栈的操作
【题目】
将单链表作为栈,写出初始化栈、判空栈、进栈和出栈操作。
【实验目的】
掌握初始化栈、判空栈、进栈和出栈的基本操作的实现
【分析】
程序中栈顶指针采用两级指针实现操作的,这样不用返回栈顶指针了,且一个函数完成一个基本操作,所以用一个菜单来实现反复的操作。
【程序】
#include<stdio.h>
#include<malloc.h>
typedef struct node{
int value;
struct node *next;
}stackNode,*LinkStack;
void initStack(LinkStack *topPt) //初始化栈
{*topPt=NULL;}
int isEmpty(LinkStack top) //判空栈
{return top==NULL;}
void push (LinkStack *topPt,int e) //进栈
{stackNode *p;
p=(stackNode*)malloc(sizeof(stackNode));
p->value=e;p->next=*topPt;
*topPt=p;
}
int pop(LinkStack *topPt,int *vPt) //出栈
{ stackNode *p;
if (isEmpty(*topPt)) return 0;
p=*topPt;*vPt=p->value;
*topPt=p->next;
free(p);return 1;
}
main()
{int choice=1,e,i;
LinkStack top,p;
initStack(&top);
while (choice!=4)
{printf("\t1:push\n");
printf("\t2:pop\n");
printf("\t3:show the stack\n");
printf("\t4:exit\n");
scanf("%d",&choice);
if(choice==1) {printf("input an element(int):");
scanf("%d",&e);
push(&top,e);
}
else if(choice==2){i=pop(&top,&e);
if(i==0) printf("Stack is empty\n" );
else printf("the poped value is:%d\n",e);
}
else if(choice==3){p=top;
printf("all element:");
while(p)
{printf("%3d",p->value);
p=p->next;
}
}
else if(choice!=4)printf("error\n");
}
}
图3 实验二A栈操作运行界面
实验二B 循环队列的操作
【题目】
将顺序表作为队列,写出初始化、判空、入队和出队操作。
【实验目的】
掌握顺序表上实现循环队列方法,掌握初始化队列、入队列和出队列的操作实现,掌握队列满和空的条件。
【分析】
程序中用动态数组来实现循环队列,并通过结构体指针来操作循环队列。
【程序】
#include<stdio.h>
#include<malloc.h>
typedef struct{
int queueSize;
int *q;
int head;
int tail;
}sQueue;
void initQueue(sQueue *qPt,int size) //初始化循环队列
{qPt->queueSize=size;
qPt->q=(int*)malloc(size*sizeof(int));
qPt->head=qPt->tail=0;
}
int isEmpty(sQueue *qPt) //判空
{return qPt->head==qPt->tail;}
int isFull(sQueue *qPt) //判满
{return qPt->head==(qPt->tail+1)%qPt->queueSize;}
int enQ(sQueue *qPt,int x) //进队
{if (isFull(qPt)) return 0;
qPt->q[qPt->tail]=x;
qPt->tail=(qPt->tail+1)%qPt->queueSize;
return 1;
}
int deQ(sQueue *qPt,int *vPt) //出队
{if(isEmpty(qPt)) return 0;
*vPt=qPt->q[qPt->head];qPt->head=(qPt->head+1)%qPt->queueSize;
return 1;
}
main()
{sQueue sQ;int choice=1,x,i;
initQueue(&sQ,10);
while(choice!=4)
{printf("\t1:enter-sQueue\n");
printf("\t2:delete-sQueue\n");
printf("\t3:show the sQueue\n");
printf("\t4:end\n");
scanf("%d",&choice);
if(choice==1){printf("Enter an element(int):");
scanf("%d",&x);
i=enQ(&sQ,x);
if(i==0)printf("Queue is full\n");
}
else if (choice==2){i=deQ(&sQ,&x);
if (i==0)printf("Queue is empty\n");
else printf("The element of deQ is %d\n",x);
}
else if(choice==3){if(sQ.head==sQ.tail) printf("Queue is empty");
else
{printf("All element of Queue is");
i=sQ.head;
while (i!=sQ.tail)
{printf("%3d",sQ.q[i]);i=(i+1)%10;}
}
}
else if(choice!=4) printf("error\n");
}
}
图4 实验二B循环队列操作的运行界面
实验三 二叉树的操作
【实验目的】
掌握二叉树上递归和非递归的前序、中序、后序遍历算法。
【实验三题目1】
编写递归算法,将二叉树中所有结点的左右子树相互交换。
【分析】
本题按前序遍历算法实现二叉树中所有结点的左右子树相互交换,即按前序的顺序判断结点的子树是否为空,若非空则左右子树相互交换。
【程序】
#include<stdio.h>
#include<malloc.h>
typedef struct binode{
int data;
struct binode *lchild,*rchild;
}binode,*bitree;
typedef struct{
bitree elem[100];
int top;
}stack;
bitree creat_bt(){ //按扩展前序建二叉树
bitree t;int x;
scanf("%d",&x);
if (x==0) t=NULL;
else { t=(bitree)malloc(sizeof(binode));
t->data=x;
t->lchild=creat_bt();
t->rchild=creat_bt();
}
return t;
}
void exchange(bitree t) //左、右子树交换
{bitree p;
if(t!=NULL)
{ p=t->lchild;t->lchild=t->rchild;
t->rchild=p;
exchange(t->lchild);
exchange(t->rchild);
}
}
void inorder(bitree bt) //递归的中序遍历
{ if (bt){
inorder(bt->lchild);
printf("% d",bt->data);
inorder(bt->rchild);
}
}
main()
{bitree root;
printf("\n");
printf("建二叉树,输入元素:");
root=creat_bt(); /*create tree of useing preorder*/
printf("交换前的中序序列是:");
inorder(root);
exchange(root);
printf("\n交换后的中序序列是:");
inorder(root);
printf("\n");
}
图5 二叉树左右子树交换运行界面
【实验三题目2】
编写非递归算法,求二叉树中的叶结点数。
【分析】
用栈来实现二叉树的非递归算法,本题用非递归的中序遍历算法求叶子。
【程序】
#include<stdio.h>
#include<malloc.h>
#define M 20
typedef struct binode{
int data;
struct binode *lchild,*rchild;
}binode,*bitree;
void preorder(bitree t) //非递归的前序遍历
{ int top=0;
bitree p,s[M];
p=t;
while (top>0||p)
{while(p!=NULL)
{ printf("% d",p->data);
if(p->rchild!=NULL);
s[top++]=p->rchild;
p=p->lchild;
}
if(top>0) p=s[--top];
}
}
int inorderleaf(bitree t) // 用非递归的中序遍历求叶子数
{ int top=0,n=0;
bitree p,s[M];
p=t;
while (p||top>0){
while(p!=NULL)
{ s[top++]=p;
p=p->lchild;
}
if(top>0) {p=s[--top];
if( p->lchild==NULL && p->rchild==NULL ) n++;
p=p->rchild;}
}
return n;
}
bitree creat_bt(){ //按扩展前序建二叉树
bitree t;int x;
scanf("%d",&x);
if (x==0) t=NULL;
else { t=(bitree)malloc(sizeof(binode));
t->data=x;
t->lchild=creat_bt();
t->rchild=creat_bt();
}
return t;
}
main()
{bitree root;
printf("\n");
printf("建树,输入元素: ");
root=creat_bt();
printf("前序序列为:");
preorder(root);
printf("\n叶结点数=%d",inorderleaf(root));
printf("\n");
}
图6 求二叉树叶结点数运行界面
【实验三题目3】
编写按层次顺序(同一层自左至右)遍历二叉树的算法。
【分析】
用队列实现二叉树的层次遍历。
【程序】
#include <stdio.h>
#include<malloc.h>
#define maxn 20
typedef struct node {
char data;
struct node *lchild;
struct node *rchild;
}bnode,*bitree;
void treelevel(bnode *t) //层次遍历
{
bnode *q[maxn],*p;
int front,rear;
front=rear=0;
if (!t) return;
q[rear]=t; //树根进队
rear =(rear+1)%maxn;
while (front!=rear) //判队列空否
{
p=q[front]; //出队
front=(front+1)%maxn;
printf ("%c",p->data);// 输出
if (p->lchild) {//左子树不空
q[rear]=p->lchild;
rear=(rear+1)%maxn;
}
if (p->rchild) {//右子树不空
q[rear]=p->rchild;
rear=(rear+1)%maxn;
}
}
}
bnode *creat_bt(){
bnode *t;char x;
scanf("%c",&x);
if (x==' ') t=NULL;
else { t=(bnode *)malloc(sizeof(bnode));
t->data=x;
t->lchild=creat_bt();
t->rchild=creat_bt();
}
return t;
}
void preorder(bitree t)
{
if(t!=NULL)
{ printf("%c",t->data);
preorder(t->lchild);
preorder(t->rchild);
}
}
main()
{bnode *t;
printf("\t建树,输入元素(char):");
t=creat_bt();
printf("\t二叉树的前序为:");
preorder(t);
printf("\n\t二叉树的层次序为:");
treelevel(t);
printf("\n");
}
图7 二叉树层次序遍历运行界面
实验四 图的遍历操作
【实验四题目1】
图在邻接矩阵存储结构上的深度优先遍历算法实现。
【实验目的】
掌握图的邻接矩阵存储算法、掌握深度优先遍历算法及其实现。
【分析】
首先键盘输入图的顶点和边信息存放邻接矩阵中,然后用递归的深度优先遍历算法进行遍历,在遍历过程中用全局变量visited数组标记访问过的顶点。
【程序】
#include<stdio.h>
#define Max 10
typedef enum{FALSE,TRUE} Boolean;//定义布尔类型
typedef struct{
char vexs[Max];
int edges[Max][Max];
int n,e;
}MGraph; //定义图的邻接矩阵存储类型
Boolean visited[Max];//定义全局变量
void CreateMGraph(MGraph *G)//图用邻接矩阵存储
{int i,j,k;
printf("输入图的顶点数n,边数e:");
scanf("%d,%d",&G->n,&G->e);
for(i=0;i<G->n;i++) //邻接矩阵置0
for(j=0;j<G->n;j++)
G->edges[i][j]=0;
printf("输入各条边:\n");
for(k=0;k<G->e;k++)
{ scanf(" %d,%d",&i,&j);//输入一条边
G->edges[i][j]=1;
G->edges[j][i]=1;
}
}
void outm(MGraph *G)//输出邻接矩阵
{int i,j;
for(i=0;i<G->n;i++)
{for(j=0;j<G->n;j++)
printf("%3d",G->edges[i][j]);
printf("\n");}
}
void DFSM(MGraph *G,int i) //深度优先遍历
{int j;
printf("%3d",i);
visited[i]=TRUE;
for(j=0;j<G->n;j++)
if (G->edges[i][j]==1 && !visited[j])
DFSM(G,j);
}
void DFSTraverse(MGraph *G)
{int i;
for(i=0;i<G->n;i++)//初始化visited标记数组
visited[i]=FALSE;
for(i=0;i<G->n;i++)
if(!visited[i]) DFSM(G,i);//调用深度优先遍历函数
}
main()
{MGraph G;
printf("创建邻接矩阵\n");
CreateMGraph(&G);
printf("\n邻接矩阵为:\n");
outm(&G);
printf("\n深度优先遍历序列为:");
DFSTraverse(&G);
printf("\n");
}
图8 邻接矩阵上的深度优先遍历运行界面
【实验四题目2】
图在邻接表存储结构上的广度优先遍历算法的实现。
【实验目的】
掌握创建邻接表,掌握广度优先遍历算法及实现。
【分析】
首先创建图的邻接表,然后用队列来实现图的广度优先遍历算法。
【程序】
#include<stdio.h>
#include<malloc.h>
#define Max 10
typedef enum{FALSE,TRUE} Boolean;
typedef struct node{
int adjvex;
struct node *next;
}EdgeNode; //定义边类型
typedef struct vnode{
char vextex;
EdgeNode *firstedge;
}VertexNode; //定义顶点类型
typedef struct{
VertexNode adjlist[Max];
int n,e;
}ALGraph;//定义图的邻接表类型
Boolean visited[Max];
void CreateALGraph(ALGraph *G)//建邻接表
{ EdgeNode *s;
int i,j,k;
printf("输入图的顶点数n,边数e:");
scanf("%d,%d",&G->n,&G->e);
printf("输入各顶点值(char):");
for(i=0;i<G->n;i++) //建邻接表中的顶点表
{scanf(" %c",&G->adjlist[i].vextex);
G->adjlist[i].firstedge=NULL;
}
printf("输入各条边(序号):\n");
for(k=0;k<G->e;k++) //建邻接表中的边表
{scanf("%d,%d",&i,&j);
s=(EdgeNode *)malloc(sizeof(EdgeNode));
s->adjvex=j;
s->next=G->adjlist[i].firstedge;
G->adjlist[i].firstedge=s;
s=(EdgeNode *)malloc(sizeof(EdgeNode));
s->adjvex=i;
s->next=G->adjlist[j].firstedge;
G->adjlist[j].firstedge=s;
}
}
void BFS(ALGraph *G,int k) //广度优先遍历
{ EdgeNode *p;
int i,Q[Max],front,rear;
front=rear=0;
printf("%c",G->adjlist[k].vextex);
visited[k]=TRUE;
rear=(rear+1)%Max;
Q[rear]=k;
while (front!=rear)
{front=(front+1)%Max;
i=Q[front];
p=G->adjlist[i].firstedge;
while (p)
{if(!visited[p->adjvex])
{printf(" %c",G->adjlist[p->adjvex].vextex);
visited[p->adjvex]=TRUE;
rear=(rear+1)%Max;
Q[rear]=p->adjvex;
}
p=p->next;
}
}
}
void print(ALGraph G)//输出邻接表
{int i;EdgeNode *p;
for(i=0;i<G.n;i++)
{ printf("\n%c-->",G.adjlist[i].vextex);
p=G.adjlist[i].firstedge;
while (p!=NULL)
{printf("%3d",p->adjvex);
p=p->next;
}
// printf("\n");
}
}
main()
{ALGraph G;
int v;
printf("创建邻接表\n");
CreateALGraph(&G);
printf("邻接表为:");
print(G);
for(v=0;v<G.n;v++)
visited[v]=FALSE;
printf("\n广度优先遍历序列为:");
for(v=0;v<G.n;v++)
if(!visited[v]) BFS(&G,v);
printf("\n");
}
图9邻接表上广度优先遍历运行界面
实验五 树的动态查找
【题目】
二叉排序树上查找结点x,若不存在,则插入;若存在,则删除。
【实验目的】
掌握二叉排序树的查找、插入和删除算法及其算法的实现。
【分析】
本题用非递归方法实现二叉排序树的动态查找的,首先从树根开始查找,找到后调用删除函数删除该结点;若找到不,则调用插入函数插入该结点。
【程序】
#include<stdio.h>
#include<malloc.h>
#define M 100
typedef struct binode{
int data;
struct binode *lchild,*rchild;
}binode,*bitree;//定义二叉链表类型
void preorderf(bitree t)//前序遍历
{ int top=0;
bitree p,s[M];
p=t;
do
{while(p!=NULL)
{printf("%d\t",p->data);
if(p->rchild!=NULL);
s[top++]=p->rchild;
p=p->lchild;
}
if(top>=0) p=s[--top];
}while (top>=0);
}
bitree ins(bitree t ,bitree f,int x)//二叉排序树中插入x
{ bitree s;
s=(bitree)malloc(sizeof(binode));
s->data=x;s->lchild=s->rchild=NULL;
if (t==NULL) t=s;
else if (s->data<f->data) f->lchild=s;
else f->rchild=s;
return t;
}
bitree del(bitree t ,bitree p,bitree f) //删除二叉排序树中p指的结点
{bitree q,child; //t为根指针、p指被删结点、f是p的前驱指针
if (p->lchild&&p->rchild){//被删结点有左、右子树
q=f=p;p=p->rchild;
while (p->lchild!=NULL){//找p的中序后继
f=p;p=p->lchild;
}
q->data=p->data;//
}//p转化为只有一个子树了
if (p->lchild) child=p->lchild; //被删结点有左子树
else child=p->rchild; 被删结点有右子树
if (f==NULL)t=child;
else if (p==f->lchild)f->lchild=child;
else f->rchild=child;
free (p);
return t;
}
void main()
{bitree root=NULL,p,f;
int x;
printf("\n输入x值:");
scanf("%d",&x);
while (x!=0)
{ p=root;f=NULL;
while(p &&p->data!=x)
{ f=p;
if (x<p->data) p=p->lchild;
else p=p->rchild;
}
if (p==NULL) {root=ins(root,f,x);printf("插入完成");}
else {root=del(root,p,f);printf("删除完成");}
printf("\n继续输入x,直到输入0为止");
scanf("%d",&x);
}
printf("\n二叉排序树的前序为;");
preorderf(root);
printf("\n");
}
图10 二叉排序树的动态查找运行界面
实验六 排序算法的实现
【实验六题目1】
链表直接插入排序的算法的实现。
【实验目的】
掌握插入排序的算法及在链式存储结构上的实现方法。
【分析】
本程序先建无序的单链表,然后从第二个结点(由r指针指向)开始的每个结点依次插入到前面有序链表中,有序链表的尾指针是q。
【程序】
#include<stdio.h>
#include<malloc.h>
typedef int elemtype;
typedef struct node{
int data;
struct node *next;
}lnode,*linklist;
linklist creat() //创建带头单链表
{linklist p,head;int x;
head=(linklist)malloc(sizeof(lnode));
p=head;
scanf("%d",&x);
while (x)
{p->next=(linklist)malloc(sizeof(lnode));
p=p->next,p->data=x;scanf("%d",&x);
}
p->next=NULL;
return head;
}
void insertsort(linklist head)//插入排序
{linklist p,q,r;
q=head->next; r=q->next; //q指向有序表的尾
while (r ) // r指向无序链表的首端
{p=head;
while ((p->next->data<=r->data) && p!=q)//查找插入位置
p=p->next;
if(p->next->data>r->data)
{q->next=r->next; r->next=p->next; p->next=r;}
else q=q->next;
r=q->next ;
}
}
output(linklist L)
{L=L->next;
while (L)
{printf("%3d",L->data);
L=L->next;}
}
main()
{linklist L;
printf("\n建链表,输入序列(0表示结束):");
L=creat();
insertsort(L);
printf("\n链式直接插入排序后的序列:");
output(L);
printf("\n");
}
图11 链表插入排序的运行界面
【实验六题目2】
试以单链表为存储结构实现简单选择排序的算法。
【实验目的】
掌握选择排序的算法及在链式存储结构上的实现方法。
【分析】
在带头的无序链表中选出最小结点放到有序链表的尾端,尾端由指针p指向,最小结点由r指向。
【程序】
#include<stdio.h>
#include<malloc.h>
typedef int elemtype;
typedef struct node{
int data;
struct node *next;
}lnode,*linklist;
linklist creat()
{linklist p,head;int x;
head=(linklist)malloc(sizeof(lnode));
p=head;
scanf("%d",&x);
while (x)
{p->next=(linklist)malloc(sizeof(lnode));
p=p->next,p->data=x;scanf("%d",&x);
}
p->next=NULL;
return head;
}
void selectsort(linklist head) {//选择排序
linklist p,q,r,s;
p=head;
while (p->next){ //p链表中找出最小
q=p->next; r=p;
while (q->next!=NULL) // 找出最小值由r指向
{if (q->next->data<r->next->data) r=q;
q=q->next;
}
if (r!=p) {s=r->next; r->next=s->next;
s->next=p->next;p->next=s;}//最小结点插在p后
p=p->next;
}
}
output(linklist L)
{L=L->next;
while (L)
{printf("%3d",L->data);
L=L->next;}
}
main()
{linklist L;
printf("\n建链表,输入序列(直至输入0 结束):");
L=creat();
selectsort(L);
printf("\n链式选择排序后的序列:");
output(L);
printf("\n");
}
图12 链表选择排序的运行界面