线性表
1.知识框架
2.线性表的基本术语
线性表是具有相同数据类型的n(n≥0)个数据元素的有限序列:
在线性表中ai是线性表中第i个元素的位序(位序冲1开始,数组下标从0开始),并且除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后继
3.线性表的基本操作
1 2 3 4 5 6 7 8 9 10 11 12
| InitList(&L) Length(L) LocateElem(L,e) GetElem(L,i) ListInsert(&L,i,e) ListDelete(&L,i,&e) PrintList(L) Empty(L) DestroyList(&L)
|
4.顺序表的定义
顺序表是指线性表的顺序存储方式,它用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也是相邻的。
每一个数据元素的存储位置都和线性表的起始位置相差一个和该数据元素的位序成正比的常数,因此,线性表的任一数据元素都可以随机存取,所以线性表的顺序存储结构是一种随机存取的存储结构。
5.数组分配类别
一维数组可以是静态分配,也可以是动态分配的,在静态分配时,由于数组的大小和空间已经提前固定,一旦空间占满,再加入新的数据就会产生溢出,进而导致程序崩溃,而在动态分配时,储存数组的空间是在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就会另外开辟一块更大的存储空间,用以替换原来的存储空间,从而达到扩充存储数组的目的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <stdio.h> #define MaxSize 10
typedef struct{ int data[MaxSize]; int length; }SqList;
void InitList(SqList &L){ for(int i=0;i<MaxSize;i++) { L.data[i]=0; } L.length=0; }
int main(){ SqList L; InitList(L); return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <stdio.h> #include <stdlib.h> #define InitSize 10
typedef struct{ int *data; int MaxSize int length; }SeqList;
void InitList(SeqList &L){ L.data = (int *)malloc(InitSize*sizeof(int)); L.length = 0; L.MaxSize = InitSize }
void IncreaseSize(SeqList &L,int len){ int *p = L.data; L.data = (int *)malloc((L.MaxSize+len)*sizeof(int)); for(int i=0;i<L.length;i++){ L.data[i]=p[i]; } L.MaxSize = L.MaxSize+len; free(p); }
int main(){ SeqList L; InitList(L); IncreaseSize(L,5); return 0; }
|
6.三种基本操作的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <stdio.h> #define MaxSize 10
typedef struct{ int data[MaxSize]; int length; }SqList;
void InitList(SqList &L){ for(int i=0;i<MaxSize;i++) { L.data[i]=0; } L.length=0; }
void ListInsert(SqList &L,int i,int e){ for(int j=L.length;j>=i;j--) { L.data[j]=L.data[j-1]; } L.data[i-1]=e; L.length++; }
int main(){ SqList L; InitList(L); LISTiNSERT(L,3,3); return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <stdio.h> #define MaxSize 10
typedef struct{ int data[MaxSize]; int length; }SqList;
void InitList(SqList &L){ for(int i=0;i<MaxSize;i++) { L.data[i]=0; } L.length=0; }
void ListDelete(SqList &L,int i,int e){ e=L.data[i-1]; for(int j=i;j>L.length;j++) { L.data[j-1]=L.data[j]; } L.length--; }
int main(){ SqList L; InitList(L); ListDelete(L,3,e); return 0; }
|
1 2 3
| int GetElem(SeqList L, int i){ return L.data[i-1]; }
|
1 2 3 4 5 6 7 8
| int LocateElem(SeqList L,int e){ for(int i=0;i<L.length;i++) if(L.data[i]==e) { return i+1; } return 0; }
|
7.单链表的定义
线性表的链式存储又称单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点,出存放元素自身的信息外,还需要存放一个指针
单链表作为非随机存取的存储结构,并不能直接找到表中某个特定的结点,查找某个特定的结点时,需要从表头开始遍历,依次查找。通常而言,单链表用头指针来标识一个单链表,比如单链表为L,头指针为NULL时表示一个空表,此外为了方便操作,在单链表第一个结点之前附加了一个结点,称为头结点。
1 2 3 4
| typedef struct LNode{ ElemType data; struct LNode *next; }LNode,*LinkList;
|
8.单链表的建立
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| LinkList List_TailInsert(LinkList &L){ int x; L=(LinkList)malloc(sizeof(LNode)); LNode *s,*r=L; scanf("%d",&x); while(x!=9999){ s=(LNode *)malloc(sizeof(LNode)); s->data=x; s->next=s; r=s; scanf("d",&x); } r->next=NULL; return L; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| LinkList List_HeadInsert(LinkList &L){ LNode *s int x; L=(LinkList)malloc(sizeof(LNode)); L->next=NULL; LNode *s,*r=L; scanf("%d",&x); while(x!=9999){ s=(LNode *)malloc(sizeof(LNode)); s->data=x; s->next=L->next; L->next=s; scanf("d",&x); } return L; }
|
9.按位序插入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| bool ListInsert(LinkList &L,int i,ElemType e){ if(i<0) { return false } LNode *p; int j=0; p = L; while(p!=NULL && j<i-1) { p=p->next; j++; } if(p==NULL) { return false; } LNode *s=(LNode *)malloc(szieof(LNode)); s->data = e; s->next=p->next; p->next=s; return ture; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| bool ListInsert(LinkList &L,int i,ElemType e){ if(i<1) { return false } if(i=1) { LNode *s = (Lnode *)malloc(sizeof(LNode)); s->data=e; s->next=L; L=s; return ture } LNode *p; int j=1; p = L; while(p!=NULL && j<i-1) { p=p->next; j++; } if(p==NULL) { return false; } LNode *s=(LNode *)malloc(szieof(LNode)); s->data = e; s->next=p->next; p->next=s; return ture; }
|
10.指定结点插入
1 2 3 4 5 6 7 8 9 10 11 12
| bool InsertNext(LNode *p, ElemType e) { if (p==NULL) return false LNode *s = (LNode *)malloc(sizeof(LNode)) ; if (s == NULL) RETURN FALSE; s->data = e; s->next = p->next; p->next = s; return ture; }
|
1 2 3 4 5 6 7 8 9 10 11
| bool InserstPriorNode(LNdoe *p, LNode *s) { if(p==NULL||S==NULL) return false; s->next = p->next; p->next = s; ElemType temp = p->data; p->data = s->data; s->data = temp; return ture; }
|
11.指定结点删除
1 2 3 4 5 6 7 8 9 10
| bool DeleteNode(LinkList &p) { if(p==NULL) return false; LNode *q=p->next p->data=p->next->data; p->next=q->next; free(q); return ture; }
|
12.单链表查找
1 2 3 4 5 6 7 8 9 10 11 12 13
| LNode *GetElem(LinkList L,int i) { if(i<0) return NULL; LNode *p; int j=0; p=L; while(p!=NULL && j<i<1) { p=p->next; j++; } }
|
1 2 3 4 5 6 7
| LNode *LocateElem(LinkList L,ElemType e) { LNode *p = L->next; while(p!=NULL && p->data!=e) p = p->next; return p; }
|
13.双链表初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| typedef struct DNode { ElemType data; struct DNode *prior,*next; }DNode,*DLinklist;
bool InitDLinkList(DLinklist &L) { L = (DNode *)malloc(szie(DNode)); if(L==NULL) return false; L->prior = NULL; L->next = NULL; return ture; }
|
14.双链表插入
1 2 3 4 5 6 7 8 9 10 11
| bool InsertNextDNode(DNode *p,DNode *s) { if(p==NULL ||s==NULL) return false; s->next=p->next; if(p->next!=NULL) p->next->prior=s; s->prior=p; p->next=s; return true; }
|
15.双链表删除
1 2 3 4 5 6 7 8 9 10 11 12 13
| bool DeleteNDode(DNode *p) { if (p==NULL) return false; DNode *q = p->next; if(q==NULL) return false; p->next=q->next; if(q->next!=NULL) q->next->prior=p; free(q); return true }
|
16.循环链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| typedef struct LNode { ElemType data; struct LNode *next; }LNode,*LinkList;
bool InitList(LinkList &L) { L = (LNode *)malloc(szieof(LNode)); if(L=NULL) return false; L->next = L; return true; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| typedef struct DNode { ElemType data; struct LNode *prior,*next; }DNode,*DLinkList;
bool InitDLinkList(DLinkList &L) { L = (DNode *)malloc(szieof(DNode)); if(L=NULL) return false; L->prior = L; L->next = L; return true; }
|
17.静态链表(考察不多)
静态链表:分配一整片连续的内存空间,所有结点集中安置
1 2 3 4 5 6
| #define MaxSize 10 struct Ndoe { ElemType data; int next; };
|
适用于不支持指针的低级语言和数据元素数量固定不变的场景。
18.顺序表vs链表
都属于线性表,都是线性结构
顺序表是顺序存储,优点是支持随机存取,存储密度高,但是存在大片连续看见分配不方便,改变容量不方便;链表是链式存储,优点是离散的小空间分配方便,改变容量方便,但是存在不可随机存取,存储密度低的问题
创建、销毁(考察不多)、增、删、改、查