有很多文章内容很丰富,但阅读的人很少,其之所以曲高和寡,大概是因为大部分的人看起来有难度。下面我总结了一下线性表的应用,以飨读者,为了方便初学者学习,每个程序都经过我调试运行,大家可阅之,运行之,有意见欢迎提出,欢迎留言。
基本的线性表有三种类型:顺序表、链表和静态链表,下面有三个程序,对应上述的三种链表。
顺序表:
/*------很简单的顺序线性表------*/
#include <stdio.h>
#include <stdlib.h>
#include<stdio.h> //输入输出函数头文件
#include<stdlib.h> //内存申请函数头文件
#define LIST_INIT_SIZE 10 //定义最初申请的内存的大小
#define LIST_INCREMENT 2 //每一次申请内存不足的时候扩展的大小
#define OVERFLOW false //异常抛出返回值
#define ERROR false //异常抛出返回值
#define INFEASIBLE false //异常抛出返回值
#define OK true //程序正确执行抛出返回值
typedef int ElemType; //别名声明,其实int可以用任意的名字代入
typedef bool Status; //别名声明
typedef struct SqList
{
ElemType *base;
int len;
int size;
}SqList;
void InitList(SqList &L)
{
//初始条件:无
L.base=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!L.base)
exit(OVERFLOW); //储存分配失败
L.len=0; //空表长度为0
L.size=LIST_INIT_SIZE; //初始储存容量
}
//删除节点后,后面的节点要移动
//插入的位置是给出的
Status InsertList(SqList &L, int i, ElemType e)
{
ElemType *newbase,*q,*p;
if(i<1||i>L.len+1) //插入的位置不合法
return ERROR;
if(L.len>=L.size)
{
if(!(newbase=(ElemType *)realloc(L.base,(L.size+LIST_INCREMENT)*sizeof(ElemType))))
exit(OVERFLOW);
L.base = newbase;
L.size += LIST_INCREMENT;
}
q = L.base+i-1;
for(p=L.base+L.len-1;p>=q;--p)
*(p+1) = *p;
*q = e;
++L.len;
return OK;
}
//插入节点后,后面的节点要移动
Status DeleteList(SqList &L, int i,ElemType &e)
{
ElemType *p, *q;
if(i<1||i>L.len)
return ERROR;
p = L.base+i-1;
e = *p;
q = L.base+L.len-1;
for(++p;p<=q;++p)
{
*(p-1) = *p;
}
L.len--;
return OK;
}
int compare(int x,int y)
{
return x!=y;
}
int LocateElem(SqList L, ElemType e, int type)
{
ElemType *p;
int i=1;
p = L.base;
while(i<=L.len&&compare(*p++,e))
++i;
if(i<L.len)
return i;
else
return 0;
}
Status GetElem(SqList L,int i,ElemType &e)
{
if(i<1||i>L.len)
return ERROR;
e = *(L.base+i-1);
return OK;
}
/********************** 输入函数 **********************/
void InitListALL(SqList *L)
{
L->base=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
printf("enter the length:");
scanf("%d",&L->len);
for(int i=0;i<L->len;i++)
scanf("%d",L->base+i);
}
/********************** 输出函数 **********************/
void OutList(SqList *L)
{
for(int i=0;i<L->len;i++)
printf("%d\t",*(L->base+i));
}
void Union(SqList &La, SqList Lb)
{
int i,e;
int len1 = La.len;
int len2 = Lb.len;
for (i=1;i<Lb.len;i++)
{
GetElem(Lb,i,e);
if(!LocateElem(La,e,0))
InsertList(La,++len1,e);
}
}
//La 和 Lb 都是非递减排列
void MergeList1(SqList La, SqList Lb, SqList &Lc)
{
InitList(Lc);
int i=1,j=1,k=0;
ElemType ai,bj;
while(i<=La.len&&j<=Lb.len)
{
GetElem(La,i,ai);
GetElem(Lb,j,bj);
if(ai<=bj)
{
InsertList(Lc,++k,ai);
++i;
}
else
{
InsertList(Lc,++k,bj);
++j;
}
}
while(i<=La.len)
{
GetElem(La,i++,ai);
InsertList(Lc,++k,ai);
}
while(j<=La.len)
{
GetElem(Lb,j++,bj);
InsertList(Lc,++k,bj);
}
}
void MergeList2(SqList La,SqList Lb, SqList &Lc)
{
int *pa,*pb,*pa_last,*pb_last,*pc;
pa = La.base;
pb = Lb.base;
Lc.size = Lc.len =La.len+Lb.len;
pc = Lc.base = (ElemType *)malloc(sizeof(ElemType)*Lc.size);
if(!Lc.base)
exit(OVERFLOW);
pa_last = La.base + La.len-1;
pb_last = Lb.base + Lb.len-1;
while(pa<=pa_last&&pb<=pb_last)
{
if(*pa<=*pb)
*pc++=*pa++;
else
*pc++=*pb++;
}
while(pa<=pa_last)
*pc++=*pa++;
while(pb<=pb_last)
*pc++=*pb++;
}
int main()
{
/********************** 函数声明区域 **********************/
void InitList(SqList &L);
Status ListInsert(SqList &L,int i,ElemType e);
int ListLength(SqList L);
int LocateElem(SqList L,ElemType e,int type);
int compare(int x,int y);
void Union(SqList &La,SqList Lb);
void InitListALL(SqList *L);
void OutList(SqList *L);
/********************** 程序执行区域 **********************/
SqList La,Lb; //定义顺序表La,Lb
InitListALL(&La); //建立A表
InitListALL(&Lb); //建立B表
Union(La,Lb); //把B表插入到A表中
OutList(&La); //输出A表
return 0;
}
链表:
/********************** 声明部分 **********************/
#include<stdio.h> //输入输出函数头文件
#include<stdlib.h> //内存申请函数头文件
#define LIST_INIT_SIZE 10 //定义最初申请的内存的大小
#define LIST_INCREMENT 2 //每一次申请内存不足的时候扩展的大小
#define OVERFLOW false //异常抛出返回值
#define ERROR false //异常抛出返回值
#define INFEASIBLE false //异常抛出返回值
#define OK true //程序正确执行抛出返回值
typedef int ElemType; //别名声明,其实int可以用任意的名字代入
typedef bool Status; //别名声明
int length;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
void InitListALL(LinkList &L)
{
int i=0,e;
int len;
LinkList p = L,s;
printf("Please input the length:\n");
scanf("%d",&len);
for(i=0;i<len;i++)
{
//顺序链表的空间是一次性分配的,链式链表的空间是一个节点一个节点分配的
s = (LinkList)malloc(sizeof(LNode));
scanf("%d",&e);
s->data = e;
p->next =s;
p = s;
}
}
void OutList(LinkList &L)
{
LinkList p = L->next;
while(p!=NULL)
{
printf("%d",p->data);
p = p->next;
}
}
Status GetElem(LinkList L,int i,ElemType &e)
{
int j = 1;
LinkList p = L->next;
while(p&&j<i)
{
p = p->next;
j++;
}
if(!p||j>i)
return ERROR;
e = p->data;
return OK;
}
//在第i个位置之前插入新节点e
Status ListInsert(LinkList L, int i, ElemType e)
{
int j = 0;
LinkList p=L,s;
while(p&&j<i-1)
{
p = p->next;
}
if(p==NULL||j>i)
{
return ERROR;
}
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
//这个函数还是很巧妙的
void MergeList(LinkList &La,LinkList &Lb,LinkList &Lc)
{
LinkList pa,pb,pc;
pa = La->next;
pb = Lb->next;
Lc = pc = La; //用La的头结点作为Lc的头节点
while(pa&&pb)
{
if(pa->data<=pb->data)
{
pc->next = pa;
pc = pa;
pa = pa->next;
}
else
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
pc->next = pa?pa:pb;
free(Lb);
}
int main()
{
/********************** 函数声明区 **********************/
void InitListALL(LinkList &L);
void OutList(LinkList &L);
/********************** 程序执行区 **********************/
LinkList La,Lb,Lc;
La=(LinkList)malloc(sizeof(LNode));
Lb=(LinkList)malloc(sizeof(LNode));
InitListALL(La);
InitListALL(Lb);
MergeList(La,Lb,Lc);
OutList(Lc);
return 0;
}
静态链表:
/********************** 声明部分 **********************/
#include<stdio.h> //输入输出函数头文件
#include<stdlib.h> //内存申请函数头文件
#define LIST_INIT_SIZE 10 //定义最初申请的内存的大小
#define LIST_INCREMENT 2 //每一次申请内存不足的时候扩展的大小
#define OVERFLOW false //异常抛出返回值
#define ERROR false //异常抛出返回值
#define INFEASIBLE false //异常抛出返回值
#define OK true //程序正确执行抛出返回值
#define DestroyList ClearList //两个函数实现的效果是一样的
#define MAX_SIZE 100 //最大的初始容量
typedef int ElemType; //别名声明,其实int可以用任意的名字代入
typedef bool Status; //别名声明
/********************** 结构体定义部分 **********************/
typedef struct{
ElemType data;
int cur;
}component,SLinkList[MAX_SIZE];
void InitList(SLinkList L)
{
int i;
L[MAX_SIZE-1].cur = 0; //L的最后一个元素只想表头
for(i=0;i<MAX_SIZE;i++)
{
L[i].cur = i+1;
}
L[MAX_SIZE-2].cur = 0;
}
int Length;
void InitListAll(SLinkList L)
{
int i;
printf("Please input the list you want\n");
scanf("%d",&Length);
for(i=1;i<=Length;i++)
scanf("%d",&L[i].data);
}
void OutList(SLinkList L)
{
int i;
for(i=1;i<=Length;i++)
printf("%d ",L[i].data);
}
int LocateElem(SLinkList L,ElemType e)
{
int i = L[0].cur;
while(i&&L[i].data!=e)
i = L[i].cur;
return i;
}
//判断链表是否为空,
int IsEmpty(SLinkList L)
{
int i;
i = L[0].cur;
if(L[0].cur)
L[0].cur = L[i].cur;
return i;
}
//回收指定下标的节点到备用链表中
void Free(SLinkList L,int k)
{
L[k].cur = L[0].cur;
L[0].cur = k;
}
/********************** 一次输入两个集合的元素,建立(A-B)U(B-A)的静态链表,S为其头指针。假设备用空间足够大,L[0]为其头指针 **********************/
void differecce(SLinkList &L,int &S)
{
int r,m,n,i,j;
InitList(L); //初始化备用空间
S=IsEmpty(L); //生成S的头结点
r=S; //r指向S的当前最后节点
printf("please enter the length of A and B:");
scanf("%d %d",&m,&n); //输入A和B的元素个数
Length=m+n;
for(j=1;j<=m;++j) //建立A的链表
{
i=IsEmpty(L); //分配节点
scanf("%d",&L[i].data); //输入A的元素值
L[r].cur=i; //插入到表尾
r=i;
}
L[r].cur=0; //尾节点的指针为空
int b,p,k;
for(j=1;j<=n;++j) //依次输入B元素,若不在当前表中,则插入,否则删除
{
scanf("%d",&b);
p=S;
k=L[S].cur; //K指向集合A中第一个结点
while(k!=L[r].cur&&L[k].data!=b)
{//在当前表中查找
p=k;
k=L[k].cur;
}
if(k==L[r].cur) //假如当前表中没有所说的这个元素
{
i=IsEmpty(L);
L[i].data=b;
L[i].cur=L[r].cur;
L[i].cur=i;
}
else //该元素已经在表中,删除之
{
Length--;
L[p].cur=L[k].cur;
Free(L,k);
if(r==k)
r=p;
}
}
}
int main()
{
/********************** 函数声明区 **********************/
void InitList(SLinkList L);
void InitListAll(SLinkList L);
void OutList(SLinkList L);
int LocateElem(SLinkList L,ElemType e);
/********************** 程序执行区 **********************/
int e,number;
SLinkList L;
InitList(L);
InitListAll(L);
printf("please enter the number you want:");
scanf("%d",&e);
number=LocateElem(L,e);
// OutList(L);
printf("the place is %d\n",number);
return 0;
}