上传源码,学习交流,有什么需要改进的地方还希望各位给予指点。
参考书目:《数据结构(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;
}
运行输出结果如下: