寻寻寻寻20.11.30更新:
1.增加PTA部分线性表例题。
2.增加顺序表特点描述。
一、顺序表;
(1)特点:
顺序存储,随机存取(就是通过首地址和元素的位序号值可以在O(1)的时间内找到指定的元素。);
读取数据方便,插入和删除将会移动较多的数据(时间复杂度高)。
(2)C语言描述:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define MAX_SIZEL 1000
#define ElemType int
#define Status int
#define OK 1
#define OVERFLOW -1
#define ERROR 0
#define INCERMENT 10
using namespace std;
typedef struct{
ElemType *elem;//储存空间基址;
int length;//当前长度
int listsize;//目前容量
}SqList;
//初始化
Status InitList_Sq(SqList &L){
//初始化顺序表。
L.elem=new ElemType[MAX_SIZEL];
if(!L.elem)exit(OVERFLOW);
L.length=0;
L.listsize=MAX_SIZEL;
return OK;
}
//读取元素
Status GetElem(SqList &L,int i,ElemType&e){
//获取L中第i个元素并用e去返回。
if(i<1||i>L.length)return ERROR;//元素不存在
e=L.elem[i-1];
return OK;
}
//指定位置插入元素
Status ListInsert(SqList& L,int i,ElemType e){
//在顺序表第i个元素前插入元素e;
//判断表满
ElemType* newbase;
if(i<1||i>L.length+1)return ERROR;
if(L.length>=L.listsize){
newbase=(ElemType*)realloc(L.elem,(L.length+INCERMENT)*sizeof(ElemType));
if(!newbase)exit(OVERFLOW);
L.elem = newbase;
L.listsize+=INCERMENT;
}
ElemType *q,*p;
q=&(L.elem[i-1]);
for(p=&(L.elem[L.length-1]);p>=q;p--){
*(p+1)=*p;
}
*p=e;
++L.length;
return OK;
}
//删除元素
Status ListDelete_Sq(SqList &L,int i,ElemType &e){
if(i<1||i>L.length)return ERROR;
ElemType* q,*p;
p=&(L.elem[i-1]);//获取删除位置元素;
e=*p;
q=L.elem+L.length-1;
for(++p;p<=q;++p){
*(p-1)=*p;
}
--L.length;
return OK;
}
二、单链表
(1)特点
随机储存,顺序读取;逻辑上相邻,储存物理位置不相邻。
为操作方便统一,常常在第一个结点前加一个头节点,指向首结点
(2)C语言描述
#include <stdio.h>
#include <stdlib.h>
#define ElemType int
#define Status int
#define ERROR 0
#define OK 1
typedef struct LNode{
ElemType date;
struct LNode *next;
}LNode,*LinkList;
//结点初始化
void InitLink_L(LNode *p){
p=(LNode*)malloc(sizeof(LNode));
p->date=0;
p->next=NULL;
}
//获取结点数据
Status GetElem_L(LinkList L,int i,ElemType &e){
//L是单链表的头指针以e返回第i个元素的值;
LinkList P;int j;
P=L->next; j=1;
while(P&& j<i){
P=P->next;
j++;
}
if(P||j>i)return ERROR;
e = P->date;
return OK;
}
//在指定位置插入节点
Status ListIncert_L( LinkList &L,int i,ElemType &e){
//L为带头节点的链表的头指针。
//在i的位置插入元素e
LinkList p=L;int j=0;
while(p&&j<i-1){
p=p->next;++j;//寻找第i个节点;
}
if(!p)
return ERROR;
LNode* s;
InitLink_L(s);
s->date=e;
s->next=p->next;
p->next=s;
return OK;
}
//删除指定位置的结点
Status DeletList(LinkList &L,int i,ElemType &e){
LinkList p=L;int j=0;
while(p->next&&j<i-1){
p=p->next;
++j;
}
if(!p->next)return ERROR;
e=p->date;
LNode* a;
a=p->next;//设a中介结点的必要性是释放内存,防止内存泄漏;
p->next=a->next;
free(a);
return OK;
}
三、有序表与无序表的应用
内容较为简单,只转载ppt
四、PTA例题
(1)顺序表
1、若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用哪种存储方式最节省时间?
A.双链表
B.单循环链表
C.带头结点的双循环链表
D.顺序表
由顺序表特点可较易得,D更合适。
2、要将一个顺序表{a0,a1,a2……an-1}中数据元素ai(0≤i≤n-1,这是第i+1个数据)删除,需要移动( )个数据元素。
删除第i个元素后,之后的元素是从ai+1到an-1,两者之间的元素易得出 n - i -1。
3、若长度为n的线性表采用顺序结构,在第i个数据元素之前插入一个元素,需要它依次向后移动()个元素。
在第i个元素前插入一个元素,则需要移动的元素为从第i到第n,不动的元素个数有i-1个,所以需要向后移动n-i+1个元素。
4、线性表L=(a1, a2 ,……,an )用一维数组表示,假定删除线性表中任一元素的概率相同(都为1/n),则删除一个元素平均需要移动元素的个数是()。
依次分析,需要移动的个数分别为:n-1,n-2,n-3,…… ,0,又是一个公差为1的等差数列,但我们只需要求出他的平均值为(n-1)/2。
(2)单链表
1、设h为不带头结点的单向链表。在h的头上插入一个新结点t的语句是:t->next=h; h=t;
主要是不带头结点,注意别错了。
2、将长度为n的单链表连接在长度为m的单链表之后的算法的时间复杂度为( )。
答案:O(m),注意需要遍历m次在连接。
3、对于一非空的循环单链表,h和p分别指向链表的头、尾结点,则有:p->next == h
注意区分首结点、头结点。没啥好说的,仔细认真。
4、在双向循环链表结点p之后插入s的语句是:
s->prior=p; s->next=p->next; p->next->prior=s; p->next=s;
5、非空的循环单链表head的尾结点(由p所指向)满足(p->next == head)。
前提是head为头结点。