2.1 线性表的定义
线性结构的特点是数据元素之间是一种线性关系,在一个线性表中,数据元素的类型是相同的,或者说线性表是由同一类型的数据元素构成的线性结构.综上所诉:线性表是具有相同数据类型的n(n>=0)个数据元素的有限序列.
2.2 线性表的顺序存储以及运算实现
//线性顺序存储的定义
#define Maxsize 100
typedef int DataType;
typedef struct {
DataType data[Maxsize];
int last; //用来记录线性表中最后一个元素在数组中的位置
}SeqList;
SeqList L;
//顺序表的初始化
SeqList *Init_SeqList()
{
SeqList *L;
L=new SeqList; //分配空间
if(L) //空间分配成功
{
L->last=-1;
return L;
}
else //申请不成功
return -1;
}
int Insert_SeqList(SeqList L,int i,DataType x) //插入算法
{
int j;
if(L->last+1>=Maxsize) //如果超过了预定空间大小
return -1;
if(i<1||i>L->last+2) //插入的位置是从1到n+1,n==L->last+1
return -1;
for(j=L->last;j>=i-1;j--)
L->data[j+1]=L->data[j];
L->data[i-1]=x;
L->last++;
return 1;
}
int Delete_SeqList(SeqList L,int i) //删除算法
{
if(i<1||i>L->last+1) //删除的位置从1到n,不存在则返回错误代码
return 0;
for(int j=i;j<=L->last;j++) //向前移动一位
L->data[j-1]=L->data[j];
L->last--;
return 1;
}
int Location_SeqList(SeqList L,DataType x) //按值查找
{
int j=0;
while(j<=L->last&&L->data[j]!=x)
j++;
if(j>L->last)
return -1;
else
return i;
}
2.3 顺序表的应用举例
//将顺序表重新排列成以a1为界的两部分,a1前面的数据元素的值均比a1小,a1后面数据元素的值都比a1大
void part(SeqList *L)
{
int i,j;
DataType x,y;
x=L->data[0];
for(i=1;i<=L->last;i++)
{
if(L->data[i]<x)
{
y=L->data[i];
for(j=i-1;j>=0;j--) //前面的所有数据都向后移动
{
L->data[j+1]=L->data[j];
}
L->data[0]=y;
}
}
}
//有序表的合并算法,A和B是从小到大的升序排列
void Mymerge(SeqList A,SeqList B,SeqList *C)
{
int i,j,k;
i=j=k=0;
while(i<=A.last&&j<=B.last) //依次扫描顺序表A和B中的数据元素
{
if(A.data[i]<B.data[j])
{
C->data[k]=A.data[i];
i++;
k++;
}
else
{
C->data[k]=B.data[j];
j++;
k++;
}
}
while(i<=A.last) //把A中剩下的值赋给C
{
C->data[k]=A.data[i];
i++;
k++;
}
while(j<=B.last) //把B中剩下的值赋给C
{
C->data[k]=B.data[j];
j++;
k++;
}
C->last=k-1;
}
//比较线性表大小的算法
int compare(int A[],int B[],int m,int n)
{
int i,j,ms,ns;
int AS[],BS[];
i=0;
while(i<=m&&i<=n&&A[i]==B[i])
i++; //找最大的共同前缀
ms=ns=0;
for(j=i;j<n;j++)
{
AS[ms]=A[j];
ms++;
}
for(j=i;j<n;j++)
{
BS[ms]=B[j];
ns++;
}
if(ms==ns&&ms==0)
return 0; //AS,BS是空表,则A和B是相等
else
if(ms==0&&ns>0||ms>0&&ns>0&&AS[0]<BS[0]) //A表小于B表
return -1;
else
return 1; //A表大于B表
}
2.4 线性表的链存储和运算实现
typedef struct Node //链表的结构定义
{
DataType data;
struct Node *next;
}LNode,*LinkList;
//建立链表,第一种从头部插入,头插法
LinkList *Init_LinkList()
{
LinkList L;
LNode s;
int x;
L=NULL; //首先置为空表
cin>>x;
while(x!=Flag)
{
s=new LNode;
s->data=x;
s->next=L;
L=s;
cin>>x;
}
return L;
}
//从尾部插入
LinkList *Init_LinkList2()
{
LinkList L;
LNode *r,*s;
L=r=NULL;
int x;
cin>>x;
while(x!=Flag)
{
s=new LNode;
s->data=x;
if(L==NULL) //第一个节点的处理
L=s;
else
r->next=s; //其他节点的处理
r=s; //r指向新的尾节点
cin>>x;
}
return L;
}
//带头节点的求表长
int length_LinkList1(LinkList L)
{
LNode *p;
int i=0;
p=L;
while(p->next)
{
p=p->next;
i++;
}
return i; //P指向第i个节点
}
//不带头节点的单链表求表长
int length_LinkList2(LinkList L)
{
LNode *p;
int i=0;
p=L;
while(p)
{
i++;
p=p->next;
}
return i; //指向第i+1个节点
}
//按序号查找,带头节点
int Get_LinkList(LinkList L,int i)
{
int j=1;
LNode *p;
p=L->next;
while(p!=NULL&&j<i)
{
p=p->next;
j++:
}
return p;
}
//按值查找,带头节点的链表
int *Location_LinkList(LinkList L,DataType x)
{
LNode *p;
p=L->next;
while(p!=NULL&&p->data!=x)
p=p->next;
return p;
}
//插入运算,关键在于找到前一个节点
LinkList Insert_LinkList(LinkList L,int i,DataType x)
{
LNode *p,*s;
p=Get_LinkList(LinkList L,i-1);
if(p==NULL) //如果第i-1个节点不存在
return 0;
else
{
s=new LNode;
s->data=x;
s->next=p->next;
p->next=s;
return 1;
}
}
//删除节点
LinkList Detele_LinkList(LinkList L,int i)
{
LNode *s,*p;
p=Get_LinkList(L,i-1);
if(p==NULL)
return -1;
else
if(p->next==NULL)
return 0;
else
{
s=p->next; //s指向第i个节点
p->next=s->next; //从链表中删除节点s
delete s; //释放空间
return 1;
}
}
//将两个单循环链表链接起来,r1,r2是循环链表的尾指针
p=r1->next; //保留H1的头指针
r1->next=r2->next->next; //头尾相接
delete r2->next; //删除H2的头节点
r2->next=p; //组成循环链表
//双向链表的定义
typedef struct DLnode
{
DataType data;
struct DLnode *prior,*next;
}DLnode,*DLinkList;
//插入操作,s插到p的节点前面
s->prior=p->prior;
p->prior->next=s;
s->next=p;
p->prioe=s;
//删除节点
p->prior->next=p->next;
p->next->prior=p->prior;
delete p;
2.5 链表的应用
//链表的倒置,采用头插法的原理
void reverse(LinkList L)
{
LNode *p,*s;
p=L->next;
L->next=NULL;
while(p)
{
s=p;
p=p->next;
s->next=L; //将当前节点插到头节点后面(注意哲理的"后面"的理解,由于头插的方向)
L->next=s;
}
}
//删除链表中重复节点的算法
void pur_LinkList(LinkList L)
{
LNode *p,*s,*q;
p=L->next;
while(p)
{
q=p;
while(q->Next)
{
if(q->next->data==p->data)
{
s=q->next;
q->next=s->next;
delete s;
}
else
q=q->next;
}
p=p->next;
}
}
//两个链表的归并算法,A,B是递增有序的,归并成一个递减的有序链表C
LinkList merge(LinkList A,LinkList B)
{
LinkList C;
LNode *p,*q;
p=A->next;
q=B->next;
C=A;
C->next=NULL:
delete B;
while(p&&q)
{
if(p->data<q->data)
{
s=p;
p=p->next;
}
else{
s=q;
q=q->next;
}
s->next=C->next; //头插
C->next=s;
}
if(p==NULL)
p=q;
while(p) //将剩余的节点一个个摘下,插入倒C表的头部
{
s=p;
p=p->next;
s->next=C->next;
C->next=s;
}
}
2.6 算法应用
1.一个递增有序的线性表,插入一个x,插入到合适的位置,序列还是递增有序
int InsertSeq(int A[],int num,DataType x)
{
int i=num;
while(i>=0&&A[i]>x)
{
A[i+1]=A[i]; //边找边移动
i--;
}
A[i+1]=x;
num++;
return 1;
}
2.假设在长度大于1的单循环链表中,既无头节点也无指针,s为指向链表中某个节点的指针,编写删除节点s的直接前驱节点
void Deletepre(LNode *s)
{
LNode *p,*q;
p=s;
while(p->next==s)
{
q=p;
p=p->next;
}
q->next=s;
delete p;
}
3.两个单链表A和B分别代表两个集合,其元素递增,编写一个函数求A和B的交际,同样以递增的单链表存储
LinkList *inter(LinkList A,LinkList B)
{
LNode *p,*q,*r,*s;
LNode *C;
C=new LNode;
r=C;
p=A;
q=B;
while(p&&q)
{
if(p->data>q->data)
p=p->next;
else if(p->data==q->data)
{
s=new LNode;
s->data=p->data;
r->next=s;
r=s;
p=p->next;
q=q->next;
}
else
q=q->next;
r->next=NULL;
r=C->next;
delete C;
return r;
}
4. 单链表L是一个递减的有序表,时编写一个高效算法,删除表中值大于min且小于max的节点,同时释放被删除节点的空间
LinkList delete(LinkList L,int min,int max)
{
LNode *p,*q,*s;
if(L->next)
{
p=L->next;
s=L;
while(p->data>=max)
{
s=p;
p=p->next;
}
while(p!=L&&p->data>min)
p=p->next;
while(s->next!=p)
{
k=s->next;
s->next=k->next;
delete k;
}
}
}
5. 线性表用顺序存储,将前m个元素和后n个元素互换
void process(SeqList *L,int m,int n)
{
int i,k;
DataType x;
if(m<=n)
{
for(i=1;i<=m;i++)
x=L->data[0];
for(k=1;k<=L->last;k++)
L->data[k-1]=L->data[k];
L->data[L->last]=x;
}
else
{
for(i=1;i<=n;i++)
x=L->data[L->last];
for(k=L->last-1;k>=0;k--)
L->data[k+1]=L->data[k];
L->data[0]=k;
}
}
6.带头节点的单链表L的节点是按整数值递增的,将x插入,使L有序
LinkList *insert(LinkList L,int x)
{
LNode *p,*s;
p=L;
while(p->next&&x>p->next->data)
{
p=p->next;
}
s=new LNode;
s->data=x;
s->next=p->next;
p->next=s;
return L;
}