线性表
含义及特点
1.线性表的含义:是由n(n>=0)个类型相同的数据元素组成的有限序列。数据元素之间有一对一的关系。
2.线性表的特点:同一性,有穷性,有序性。
线性表的顺序存储(随机存取)
1.顺序存储结构
#define MAXSIZE 100
struct SeqList
{
ElemType elem[MAXSIZE];
int last;
};
- [1]ElemType 可以具体为int,float,char或一种struct结构类型
- [2]区分元素序号和元素在数组中下标的对应关系,元素在数组中下标为0,元素起始序号为1.
- [3]类型是模板,变量是真正的存储空间
2.顺序存储结构上的基本运算
(1)插入:在顺序表l中第i个数据元素前插入一个元素e,i的合法取值为1<=i<=l.last+2.
void InsertSeqlist(SeqList l,int i,ElemType e)
{
if(i<1 || i>l->last+2) /先判断插入位置是否合法/
{
return;
}
if(l->last>=MAXSIZE-1) / 判断最后一个元素下标是否超过表的限制*/
{
return;
}
for(int k=l->last;k>=i-1;k–)
{
l->elem[k+1]=l->elem[k];
}
l->elem[i-1]=e;
l->last++;
}
- [1]在长度为n的表中插入一元素所需移动元素的平均次数是n/2.
(2)删除:在顺序表中删除第i个数据元素,i的合法取值为1<=i<=l.last+1.
void DeleteSeqlist(SeqList *l,int i,ElemType *e)
{
if( i<1 || i>l->last+1) /判断删除位置是否合法/
{
return;
}
*e=l->elem[i-1];
for(int k=i;i<=l->last;k++)
{
l->elem[k-1]=l->elem[k];
}
l->last–;
}
- [1] 在长度为n的表中删除一元素所需移动元素的平均次数是(n-1)/2.
3.例题:(1)合并两有序线性表 (2)左奇右偶 ,左正右负(3)求并集交集 (4)约瑟夫环
eg:利用顺序表调整其为左右两部分,左边的为奇数,右边的为偶数
void AdjustSeqlist(SeqList *L)
{
int i=0,j=L->last;
int t;
while(i<j)
{
while(L->elem[i]%2!=0)
i++;
while(L->elem[j]%2==0)
j–;
if(i<j)
{
t=L->elem[i];
L->elem[i]=L->elem[j];
L->elem[j]=t;
}
}
}
线性表的链式存储
1.单链表的存储结构
typedef struct Node
{
ElemType data;
struct Node *next;
}*LinkList;
2.单链表上的基本运算
(1)初始化单链表
void InitList(LinkList *L)
{
//*L=(LinkList)malloc(sizeof(Node)); c语言中
*L=new Node;
(*L)->next=NULL;
}
(2)头插法建立单链表
void CreatFromHead(LinkList L)
{
Node *s;
char c; //这里将ElemType具体为char类型
int flag=1;
while(flag)
{
cin>>c;
if(c!=’$’)
{
//s=(Node *)malloc(sizeof(Node));
s=new Node;
s->data=c;
s->next=NULL;
s->next=L->next;
L->next=s;
}
else
flag=0;
}
}
(3)尾插法建立单链表
void CreatFromTail(LinkList L)
{
Node *s,*r;
char c; //这里将ElemType具体为char类型
int flag=1;
r=L;
while(flag)
{
cin>>c;
if(c!=’$’)
{
// s=(Node *)malloc(sizeof(Node));
s=new Node;
s->data=c;
r->next=s;
r=s;
}
else
{
flag=0;
r->next=NULL;
}
}
}
(4)插入:第i个位置前插入一个新元素e,则查找第i-1个结点,将e插入到第i和第i-1个结点之间
void InsertList(LinkList L,int i,ElemType e)
{
Node *pre,s;
pre=L;
int k=0;
while(pre!=NULL && k<i-1)
{
pre=pre->next;
k+=1;
}
if(pre!=NULL)
{
return;//插入位置不合理
}
s=new Node;
// s=(Node)malloc(sizeof(Node));
s->data=e;
s->next=pre->next;
pre->next=s;
}
(5)删除:删除第i个元素e,则查找第i-1个结点,然后删除第i个结点并释放结点空间
void DeleteList(LinkList L,int i,ElemType *e)
{
Node *pre,*r;
pre=L;
int k=0;
while(pre->next!=NULL && k<i-1)
{
pre=pre->next;
k+=1;
}
if(pre->next==NULL)
{
return;
}
r=pre->next;
pre->next=r->next;
*e=r->data;
free®;
}
3.例题:(1)合并(2)就地逆置(3)二进制数加一运算(4)以某值划分结点
eg:链表的合并
【问题描述】
两个非降序链表的并集,例如将链表1->2->3 和 2->3->5 并为 1->2->3->5,只能输出结果,不能修改两个链表的数据。
【输入形式】
第一行首先是数据的个数,然后是第一个链表的各结点值,以空格分隔。
第二行首先也是数据的个数,然后是第二个链表的各结点值,以空格分隔。
【输出形式】
合并好的链表,以非降序排列,值与值之间以空格分隔。
【样例输入】
4 4 7 10 34
7 1 4 6 29 34 34 52
【样例输出】
1 4 6 7 10 29 34 52
#include <iostream //加一个‘’>‘’
using namespace std;
typedef struct Node
{
int data;
struct Node *next;
}*LinkList;
InitList(LinkList *L)
{
*L=new Node;
(*L)->next=NULL;
}
void CreatFromTail(LinkList L,int len)
{
int data_,i;
Node *s,*r;
r=L;
for(i=1;i<=len;i++)
{
s=new Node;
cin>>data_;
s->data=data_;
r->next=s;
r=s;
}
r->next=NULL;
}
void ShowList(LinkList L)
{
Node *p=L;
while(p->next)
{
p=p->next;
cout<data<<" ";
}
}
LinkList ConnectList(LinkList La,LinkList Lb)
{
LinkList Lc;
Node *pa,*pb,*pc,*r;
pa=La->next; //pa指向La的第一个结点
pb=Lb->next;
Lc=La;
Lc->next=NULL;
r=Lc; //r始终指向Lc的表尾,初值指向Lc
while(pa!=NULL &&pb!=NULL)
{
if(pa->data<=pb->data)
{
r->next=pa;
r=pa;
pa=pa->next;
}
else
{
r->next=pb;
r=pb;
pb=pb->next;
}
}
if(pa)
{
r->next=pa;
}
else
r->next=pb;
pc=Lc->next;
while(pc->next!=NULL)
{
if(pc->data!=pc->next->data)
{
pc=pc->next;
}
else
{
pc->next=pc->next->next;
}
}
return Lc;
}
int main()
{
int lena,lenb;
LinkList La,Lb,Lc;
InitList(&La);
cin>>lena;
CreatFromTail(La,lena);
InitList(&Lb);
cin>>lenb;
CreatFromTail(Lb,lenb);
Lc=ConnectList(La,Lb);
ShowList(Lc);
return 0;
}