02-线性表
概念
线性表是具有相同特性数据元素的有限序列
线性表的逻辑结构
相同特性
把一类事物归类,方便批量处理
typedef struct{
char* name;//char *c = "abc"和char c[]="abc",前者改变其内容程序是会崩溃的,而后者完全正确。
int IDNumber;
float height;
}Human;
有限
表中元素个数为n,n无限大,n可以为0
序列
表中元素排成一列,体现了一对一的逻辑特性(每个元素有则仅有一个前驱和后继)
线性表的存储结构
顺序存储空间
int A[maxSize];//maxSize常量
int length=0;
链式存储空间
单链表
typedef struct LNode{
int data;
struct LNode *next;
}LNode;
//定义节点
LNode *L;
L=(LNode*)malloc(sizeof(LNode));//为LNode开辟空间并返回地址
A->next=B;//存储B节点的地址到A的next分量中
开始结点:第一个存储数据的结点
头结点:不存储数据的结点
尾结点:最后一个存储数据的结点
判断(单)链表是否为空
双链表
typedef struct DLNode{
int data;
struct DLNode *next;
struct DLNode *prior;
}DLNode;
DLNode *L;
L=(DLNode*)malloc(sizeof(DLNode));
A->next=B; B->next=C; C->next=D;
D->prior=C; C->prior=B; B->prior=A;
判断(双)链表是否为空
(单)循环链表
(双)循环链表
循环链表判空
不带头结点的单双循环链表
顺序存储和链式存储的特性对比–(考点)
特性对比问题
- 在顺序表中插入或删除元素可能会导致移动大量元素的连带操作(插入或删除操作发生在表尾位置例外),而链表不会
- 线性表采用顺序存储结构,必须占用一片连续的存储单元,而采用链式存储结构则不需要这样;
- 从表整体来看,一般顺序表存储空间利用率第一链表;而从单个存储单元来看,顺序表的存储空间利用率高于链表;
插入删除
单链表结点插入操作
s->next = p->next;
p->next = s;
单链表结点删除操作
p->next = s->next;
free(s);
小结
- 给链表设置头结点,可以使得在第一个数据结点之前插入一个新结点和删除第一个数据结点的操作同表中部结点的这些操作统一起来,方便写代码;
- 带头结点的链表,其头指针值不随操作而改变,可以减少错误;
双链表结点插入操作
s->next = p->next;
s->prior = p;
p->next = s;
s->next->prior = s;
双链表结点删除操作
s->prior->next = s->next;
s->next->prior = s->prior;
free(s);
建表
顺序表建表代码
int A[maxSize];
int length;
int createList(int A[],int &length){
cin>>length;
if(length > masSize)
return 0;
for(int i=0;i<length;++i){
cin>>A[i];
}
return 1;
}
单链表建表代码
单链表尾插法
void createLinkListR(LNode *&head){
head = (LNode*)malloc(sizeof(LNode));
head->next = NULL;
LNode *p = NULL,*r = head;
int n;
std::cin>>n;
for(int i=0;i<n;++i){
p = (LNode*)malloc(sizeod(LNode));
p->next = NULL;
std::cin>>p->data;
p->next = r->next;
r->next = p;
r = p;
}
}
输入: 5 12345
输出: 12345
单链表头插法
void createLinkListH(LNode *&head){
head = (LNode*)malloc(sizeof(LNode));
head->next = NULL;
LNode *p = NULL;
int n;
std::cin>>n;
for(int i=0;i<n;++i){
p = (LNode*)malloc(sizeod(LNode));
p->next = NULL;
std::cin>>p->data;
p->next = head->next;
head->next = p;
}
}
输入: 5 12345
输出: 54321
移动次数计算(顺序表)和静态链表
插入移动次数计算(顺序表)
-
在任一位置插入元素的概率为:p=1/(n+1);
-
在i位置(i的取值:0~n)之前插入元素,需要移动n-i个元素;
-
插入元素平均要移动的元素个数为:n/2
0位置:移动n个元素
1位置:移动n-1个元素
…
n位置:移动0个元素
总移动次数:(n+0)(n+1)/2
平均移动次数:【1/(n+1)】(n+0)(n+1)/2=n/2
删除移动次数计算(顺序表)
- 在任一位置删除元素的概率为:p=1/n;
- 在i位置(i的取值:0~(n-1))删除元素,需要移动n-1-i个元素;
- 删除元素平均要移动的元素个数为:(n-1)/2;
静态链表
typedef struct{ int data; int next; }SLNode; SLNode SLink[maxSize]; int p=A0; //定义一个指针 SLink[p].data; //取p指针指向的结点值,类比p->data; SLink[p].next; //取后继结点指针,类比p->next;
归并(二路归并)
顺序表归并
//m为a的长度,n为b的长度,c为归并后的顺序表
void mergearray(int a[],int m,int b[],int n,int c[]){
int i=0,j=0;
int k=0;
while(i < m&&j < n){
if(a[i]<b[j]){
c[k]=a[i];k++;i++;//c[k++]=a[i++]
}else{
c[k]=b[j];k++;j++;
}
}
while(i < m){
c[k]=a[i];k++;i++;
}
while(j < m){
c[k]=b[j];k++;j++;
}
}
链表归并-1
//归并后升序
void merge(LNode *A,LNode *B,LNode *&c){
LNode *p = A->next;
LNode *q = B->next;
LNode *r;
C = A;
C->NEXT = NULL;
free(B);
r = C;
while(p!=NULL&&q!=Null){
if(p->data <= q->data){
r->next = p;
p = p->next;
r = r->next;
}else{
r->next = q;
q = q->next;
r = r->next;
}
}
if(p!=NULL){r->next = p;}
if(p!=NULL){r->next = q;}
}
链表归并-2
//归并后降序
void merge(LNode *A,LNode *B,LNode *&c){
LNode *p = A->next;
LNode *q = B->next;
LNode *s;
C = A;
C->NEXT = NULL;
free(B);
while(p!=NULL&&q!=Null){
if(p->data <= q->data){
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}else{
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
while(p!=NULL){
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}
while(q!=NULL){
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
逆置
顺序表逆置
for(int i=left,j=right;i>j;i++,j--){
temp = a[i];
a[i]=a[j];
a[j]=temp;
}
将多个元素移动到数组某一位置之后
void reverse(int a[],int left,int right,int k){
int temp;
for(int i=left,j=right;i<left+k&&i<j;++i,--j){
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
void moveP(int a[],int n,int p){
reverse(a,0,p-1,p);
reverse(a,p,n-1,n-p);
reverse(a,0,n-1,n);
}
链表逆置
//逆置p->next到q之间的结点
while(p->next!=q){
t = p->next;
p->next = t->next;
t->next = q->next;
q->next = t;
}
取最值
链表取最值
LNode *p,*q;
int max = head->next->data;
q = p = head->next;
while(p!=NULL){
if(max < p->data){
max = p->data;
q = p;
}
p = p->next;
}