您的位置:首页 > 理论基础 > 数据结构算法

线性表的链式表示和实现

2014-04-06 20:16 411 查看
上传源码,学习交流,有什么需要改进的地方还希望各位给予指点。

参考书目:《数据结构(C语言版)》,严蔚敏

common.h

#ifndef	_COMMON_H_
#define	_COMMON_H_

#define TRUE	    1
#define FALSE		0
#define OK			1
#define ERROR		0
#define INFEASIBLE  -1
#define OVERFLOW	-2

typedef int Status;

int	   Equal(int x,int y);	//判断两个数据是否相等

#endif


common.c

/*
输入参数:x、y		待标胶的两个数
返回参数:若x与y相等,则返回0,否则返回1
函数功能:判断两个整型数是否相等
*/
int Equal(int x,int y)
{
if(x==y)
{
return 0;
}
else
{
return 1;
}
}


list.h

#ifndef _LIST_H_
#define _LIST_H_

#define ElemType int

/*链表结构*/
typedef struct List_
{
ElemType      data;
struct List_   *next;
}List;

void   InitList(List *L);
int    ListAdd(List *L,unsigned int index, ElemType data);
int    ListDelete(List *L, unsigned int index, ElemType *data);
int    ListDisp(List *L);
int    ListScanf(List *L);
unsigned int  ListLength(List *L);
int	   GetElem(List *L,unsigned int i,int *e);
int    LocateElem(List *L,int e,int (*f)());
int    ListInsert(List *L,unsigned int n,int e);	//该函数与ListAdd()类似,但建议用这个函数。

#endif


list.c

#include <stdio.h>
#include <stdlib.h>
#include "list.h"
//#include "common.h"

/*
输入参数:*L     待初始化的链表头结点
返回参数:无
函数功能:对链表头结点进行初始化
*/
void InitList(List *L)
{
L->data = 0;
L->next = NULL;
}

/*
输入参数:*L      待插入链表头结点
index   加入位置(从1开始)(例如:原链表是x(0)=10、x(1)=11、x(2)=12、x(3)=13、x(4)=14、……,现在想在第2个结点插入数字100,则得到的新链表是x(0)=10、x(1)=11、x(2)=100、x(3)=12、x(4)=13、x(5)=14、……)
(暂时不能在第0点插入,即不能插入新的链表头)
data    加入的数据
返回参数:0       成功
非0     失败(可以细分具体的参数分别代表什么意思)
函数功能:在链表的指定位置插入数据,
*/
int ListAdd(List *L,unsigned int index, ElemType data)
{
List *p = NULL;
List *newNode = NULL;

if(L == NULL || index == 0) return -1;  //输入参数错误

p = L;
while(p != NULL && (--index > 0))
{
p = p->next;
}

if(p == NULL)   return -2;     //插入位置错误

newNode = (List *)malloc(sizeof(List));
if(newNode == NULL)
{
return -3;     //内存错误
}

newNode->data = data;
newNode->next = p->next;
p->next = newNode;

return 0;   //成功
}

/*
输入参数:*L  待插入链表的头结点
返回参数:-1  该链表不存在
0  成功完成向链表输入数据
函数功能:向指定的链表输入数据,每输完一个数据按下回车,约定当输入0时自动终止输入,且不将0存入链表。
*/
int ListScanf(List *L)
{
int n;
List	*p1,*p2;

n=0;
p1=L;
p2=L;

if(L == NULL)
{
return -1;	//该链表不存在
}
//p1=(List *)malloc(sizeof(List));
scanf("%d",&p1->data);	//在向*p1指向的内存赋值时,一定要先使p1指向一个确定的存储空间。(L在别处已经定义过,是有存储空间的,所以将L赋给p也是可以的。)
//p1->next = NULL;	//这条语句也可以不要,因为L的next已经在函数ListInit(List *L)中定义过了。
while(p1->data!=0)
{
p2->next=p1;	//当第一次进入该循环时,p2实际上是指向自己的。
p2=p1;
p1=(List *)malloc(sizeof(List));
if(p1 == NULL) return -3;	//内存不够用
scanf("%d",&p1->data);
p1->next=NULL;
}
p2->next = NULL;
free(p1);
return 0;	//完成向链表输入数据。
}

/*
输入参数:*L     待删除链表头结点
index  删除位置(从1开始)
(暂时不能删除第0点的数据,即不能删除链表头)
data   保存删除的数据
返回参数:0      成功
非0    失败
函数功能:删除链表中的指定位置的数据
*/
int ListDelete(List *L, unsigned int index, ElemType *data)
{
List *p = NULL;
List *q = NULL;

if(L == NULL || index == 0) return -1;   //头结点为空

p = L;
while(p->next != NULL && (--index > 0))
{
p = p->next;
}
if(p->next == NULL)
{
return -2;       //删除位置错误
}

q = p->next;
p->next = q->next;
if(data != NULL)   *data = q->data;
free(q);

return 0;    //成功

}

/*
输入参数:*L     待显示的链表头结点
返回参数:0      成功
非0    失败
函数功能:显示链表中的所有数据(从第0位开始显示,即从头结点开始显示)
*/
int ListDisp(List *L)
{
List *p = NULL;

if(L == NULL)   return -1;   //链表不存在

p = L;

printf("\n**************** output start ****************\n");
while(p != NULL)
{
printf("%d  ", p->data);
p = p->next;
}
printf("\n**************** output end ****************\n\n\n\n");

return 0;
}

/*
输入参数:*L	待测试链表的头结点
返回参数:链表长度
函数功能:测量链表中数据元素的个数(即链表长度),若返回0则表示该链表中没有数据,即该链表不存在。
*/
unsigned int ListLength(List *L)
{
List *p = L;
int n = 0;
//if(p == NULL)	return -1;	//该链表不存在
while(p != NULL)
{
n++;
p = p->next;
}
return n;
}

/*
输入参数:L	待查找链表头
i	待提取元素的位置(从0开始,即从链表头开始),0 ≤ i ≤ ListLength(&L)
*e	将待提取元素赋给e所指变量
返回参数:-1	链表长度不够
0	成功
(也可以直接放回第i个元素的值)
函数功能:将链表L中的第i个元素的值赋给e所指变量
*/
int GetElem(List *L,unsigned int i,int *e)
{
List *p=L;
int n=0;
if(i >= ListLength(L)) return -1;	//链表长度不够
while(n!=i)
{
p = p->next;
n++;
}
*e = p->data;
return 0;	//成功
}

/*
输入参数:L		待操作链表的链表头
e		待比较元素
(*f)()	判定关系
返回参数:0~ListLength(&L)		返回L中第1个与e满足关系(*f)()的数据元素的为序
-1	链表L中不存在这样的数据元素
函数功能:返回L中第1个与e满足关系(*f)()的数据元素的为序,若这样的数据元素不存在,则返回-1
*/
int LocateElem(List *L,int e,int (*f)())
{
int n=0;
List *p=L;

while(p != NULL)
{
if((*f)(p->data,e) == 0)
{
return n;
}
p = p->next;
n++;
}
return -1;
}

/*
输入参数:*L	待插入的链表头
n	待插入位置
e	待插入数据
返回参数:-1	插入位置错误
0	插入成功
函数功能:在指定位置插入数据
*/
int ListInsert(List *L,unsigned int n,int e)
{
List *p = L,*newnode=NULL;
int i = 1;
if(p == NULL)	return -1;	//其实这一条在下面的语句也可以判断出来。
if(n == 0 || n > ListLength(L))
return -1;	//插入位置错误
while(i != n)
{
p = p->next;
i++;
}
newnode = (List *)malloc(sizeof(List));
newnode->data = e;
newnode->next = p->next;
p->next = newnode;
return 0;
}


example.h

#ifndef _EXAMPLE_H_
#define	_EXAMPLE_H_

void UnionList(List *La,List *Lb);
void MergeList(List *La,List *Lb,List *Lc);

#endif


example.c

#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include "common.h"

/*
例2-1
输入参数:*La	待合并线性表La
*Lb	待合并线性表Lb
返回参数:无
函数功能:扩大线性表La,将存在于Lb而不存在于La中的数据元素插入到La中去
*/
void UnionList(List *La,List *Lb)
{
unsigned int i,La_len,Lb_len;
int Li;
La_len = ListLength(La);
Lb_len = ListLength(Lb);
for(i = 0; i < Lb_len; i++)
{
GetElem(Lb,i,&Li);
//printf("%d",Li);
if(LocateElem(La,Li,Equal) == -1)
{
ListInsert(La,La_len,Li);
La_len++;
}
}
}

/*
例2-2
输入参数:*La/*Lb	待归并链表头结点
*Lc		归并后的链表
返回参数:无
函数功能:合并链表La和Lb于Lc
*/
void MergeList(List *La,List *Lb,List *Lc)
{
unsigned int i=0,j=0,k=0,La_len,Lb_len;
int ai=0,bj=0;
La_len = ListLength(La);
Lb_len = ListLength(Lb);
while((i < La_len) && (j < Lb_len))
{
GetElem(La,i,&ai);
GetElem(Lb,j,&bj);
if(ai <= bj)
{
if(k==0)  Lc->data = ai;
else  ListInsert(Lc,k,ai);
k++;
i++;
}
else
{
if(k==0)  Lc->data = bj;
else  ListInsert(Lc,k,bj);
k++;
j++;
}
}
while(i < La_len)
{
GetElem(La,i,&ai);
i++;
ListInsert(Lc,k,ai);
k++;
}
while(j < Lb_len)
{
GetElem(Lb,j,&bj);
j++;
ListInsert(Lc,k,bj);
k++;
}
}	//end of MergeList


main.c

//参考书目:《数据结构(C语言版)》,严蔚敏
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include "common.h"
#include "example.h"

int main(void)
{
List La,Lb,Lc;
int Li=0;

InitList(&La);
InitList(&Lb);

printf("输入La\n");
ListScanf(&La);		//约定当输入0时自动终止输入
ListDisp(&La);

printf("输入Lb\n");
ListScanf(&Lb);		//约定当输入0时自动终止输入
ListDisp(&Lb);

printf("合并La与Lb于Lc,并显示Lc\n");
InitList(&Lc);
MergeList(&La,&Lb,&Lc);
ListDisp(&Lc);

return 0;
}


运行输出结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息