一、顺序表
顺序表中元素的存储是连续的,中间不允许有空。
根据空间分配方式有静态分配和动态分配。
1.定义
(1)数据结构静态定义
#define maxSize 100
typedef struct sqlist{
int data[maxSize];
int length;
}sqList;
(2)数据结构动态定义
#define maxSize 100
typedef struct sqlist{
int *elem;//定义基地址
int length;
}sqList;
2.初始化
bool initList(sqList &L){
L.elem=new int[maxSize];
if(!L.elem) return false;
L.length=0;
return true;
}
3.取值
(1)判断i的合法性
(2)e=L.elem[i-1]
4.插入
在第i个位置之前插入一个元素e(将元素插入在第i个位置)
(1)判断i的合法性(1≤i≤L.length+1),保证连续性。
(2)移动(要移动n-i+1个元素,将下标i-1到n-1的元素向后移动)
for(int j=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j];
L.length++;
平均时间复杂度为
5.删除
(1)判断i的合法性1≤i≤L.length
(2)移动
for(int j=i+1;i<L.length;j++)
L.elem[j-1]=L.elem[j];
L.length--;
平均时间复杂度为
二、单链表
1.数据结构定义
typedef struct Lnode{
int data;
struct Lnode *next;
}Lnode,*LinkList;
2.链表创建
头插法
每次把新结点插入到头结点之后,是逆序的。
s->next=L->next;
L-next=s;
先修改没有指针标记的那一端
尾插法
每次把新结点链接到链表的尾部,是顺序的。
需要尾指针r来记录最后一个结点,尾指针在不断移动。
s->next=null;
r->next=s;
r=s;
3.取值和查找
链表的头指针不可以随意改动。
4.插入和删除
在第i个结点之前插入一个元素,必须先找到第i-1个结点。
要删除第i个结点,先找到第i-1个结点。free(s)
5.单链表就地逆置
将带有头结点的单链表就地逆置,辅助空间复杂度为O(1)
p=L->next;//第一个节点
L->next=NULL;
q=p->next;//第二个节点
while(q){ //如果p是最后一个节点,q为NULL,遇到q=q->next;会报错
//头插法插入p节点
p->next=L->next;
L->next=p;
//向后挪动
p=q;
q=q->next;
}
//处理最后一个结点
p->next=L->next;
L->next = p;
6.全部代码
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
typedef struct Lnode{
int data;//数据域
struct Lnode *next;//指针域
}Lnode,*LinkList;
//初始化链表
bool InitList_L(LinkList &L){
L=new Lnode;
if(!L){
return false;
}
L->next=NULL;
return true;
}
//头插法创建链表
void creatList_H(LinkList &L){
int n;
LinkList s;
L=new Lnode;
L->next=NULL;
cout << "请输入元素个数n:"<<endl;
cin >>n;
cout <<"请依次输入n个元素:"<<endl;
cout <<"头插法创建单链表"<<endl;
wh