1.顺序表的定义:
【1】.静态分配(大小固定,无法改变)
#include
#include
#define max 10
using namespace std;
typedef struct {
int date[max];
int lenth;
}seqlist;
void initlist(seqlist& L) {
for (int i = 0; i < max; i++) {
L.date[i] = 0;
}
}
int main() {
seqlist L;
initlist(L);
return 0;
}
【2】.动态分配:(可改变储存大小)
(以下是c语言风格的定义,c++中可用new,delete等有关面向对象的知识来写)
#include
#include
#define initsize 10
using namespace std;
typedef struct {
int* date;
int maxsize;
int lenth;
}seqlist;
void initlist(seqlist& L) {
L.date = (int*)malloc(initsize * sizeof(int));
L.lenth = 0;
L.maxsize = initsize;
}
void increalist(seqlist& L,int len) {
int* p = L.date;
L.date = (int*)malloc((L.maxsize + len) * sizeof(int));
for (int i = 0; i < L.lenth; i++) {
L.date[i] = p[i];
}
L.maxsize = L.maxsize + len;
free(p);
}
int main() {
seqlist L;
increalist(L,5);
return 0;
}
2.顺序表的插入:(最好时间复杂度O(1),最差时间复杂度O(n),平均时间复杂度O(n))
#include
#include
#define max 10
using namespace std;
typedef struct {
int date[max];
int lenth;
}seqlist;
void listinsert(seqlist& L,int i,int e) {
int j = L.lenth;
for (int j = L.lenth;j >=i; j--) {
L.date[j] = L.date[j + 1];
}
L.date[i - 1] = e;
L.lenth++;
}
int main() {
seqlist L;
listinsert(L,3,3);
return 0;
}
3.删除
For(int j=I;j
4.查找
直接查找(esay)
结构类型的查找要分别对结构体里面的数据进行查找。
单链表,双链表,循环链表
/* 链表节点结构体 */
typedef struct ListNode {
int val; // 节点值
struct ListNode *next; // 指向下一节点的指针
} ListNode;
/* 构造函数 */
ListNode *newListNode(int val) {
ListNode *node;
node = (ListNode *) malloc(sizeof(ListNode));
node->val = val;
node->next = NULL;
return node;
}
/* 在链表的节点 n0 之后插入节点 P */
void insert(ListNode *n0, ListNode *P) {
ListNode *n1 = n0->next;
P->next = n1;
n0->next = P;
}
/* 删除链表的节点 n0 之后的首个节点 */
// 注意:stdio.h 占用了 remove 关键词
void removeItem(ListNode *n0) {
if (!n0->next)
return;
// n0 -> P -> n1
ListNode *P = n0->next;
ListNode *n1 = P->next;
n0->next = n1;
// 释放内存
free(P);
}
删除指定节点:
//删除指定节点p
bool deletnode(ListNode*p){
if(p==NULL)
return falst;
ListNode*q=p->next;
p->date=q->next->date;
p->next=q->next;
free(q);
return true;
}
//当p为最后一个节点时则不成立,可用特判防止错误
循环遍历(从头节点出发,时间复杂度为O(n),可以按位查找也可以按值查找,大致相同)
/* 访问链表中索引为 index 的节点 */
ListNode *access(ListNode *head, int index) {
for (int i = 0; i < index; i++) {
if (head == NULL)
return NULL;
head = head->next;
}
return head;
}
//在p节点之后插入s节点
bool Insertnode(Dnode*p,Dnode*s){
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}/*可用特判防止p节点后没有后继节点*/
2.删除节点(同样可以用特判防止q节点的后继节点为NULL)
//删除p的后继节点q
Bool deletenode(Dnode*p){
p->next=q->next;
q->next->prior=p;
free(q);
return true;
}
3.遍历链表
可进行查找功能,例如按位查找和按值查找,平均时间复杂度都为O(n)。
(1)后向遍历
while(p!=NULL){
p=p—>next;
}
(2)1.前向遍历
while(p!=NULL){
p=p->prior;
}
2.跳过头节点前向遍历
while(p->prior!=NULL){
p=p->prior;
}
判断链表是否为空只需要判断头节点的指针是否指向自己即可
判断链表中某个节点是否是表尾节点只需要看它下一个节点是否是头节点
循环单链表只要得到某个节点的指针则可以知道任意节点这一点是与普通单链表不同的
判断链表是否为空只需要判断头节点的指针是否指向自己即可
判断链表中某个节点是否是表尾节点只需要看它下一个节点是否是头节点
双链表中的查找删除其方式与双链表相同不需特判没有逻辑错误
用数组的方式实现链表
增删不需要移动大量元素,但容量固定不可变
#define max 10
struct node {
int date;
int next;
};
void testlist() {
struct node a[max];
//后续代码
}
更多方式
1.逻辑结构
都属于线性表,都是线性结构
2.存储方式
顺序表
优点:支持随机存储,存储密度高
缺点:大片的离散空间分配不方便,改变容量不方便
链表
优点:离散的小空间分配方便改变容量方便
缺点:不可随机存储,存储密度低
3.基本操作
链表存储空间灵活性更高
顺序表 | 链表 | |
弹性(存) | - | + |
增 删 | - | + |
查 | + | - |
栈是一种只允许在一段进行删除和插入的特殊线性表
重要术语:栈顶,栈底,空栈,入栈,出栈
由于只能在一端进行插入和删除故具有先入后出的特点
1.栈的初始化
#define max 10
typedef struct {
int date[max];//静态数组存放栈中元素
int top;
}sqstack;
void inidestack(sqstack& s) {
s.top = -1;
}
void teststack() {
sqstack s;
inidestack(s);
//...
}
2.进栈
bool push(sqstack& s, int t) {
if (s.top == max - 1) {//判断栈是否爆满
return false;
}
else {
s.date[++s.top] = t;//新元素入栈
return true;
}
}
3.出栈
bool pop(sqstack& s, int &t) {
if (s.top == -1)//栈空
{
return false;
}
else {
s.date[s.top--] = t;
return true;
}
}
4.读栈顶元素
bool pop(sqstack s, int& t) {
if (s.top == -1)//栈空
{
return false;
}
else {
t = s.date[s.top];
return true;
}
}
(也可以用top=0来定义栈,入栈,出栈和判断栈是否满了都会发生改变)
5.共享栈
# define max 10
typedef struct {
int date[max];//静态数组存放栈中元素
int top0;
int top1;
}sqstack;
void inidestack(sqstack& s) {
s.top0= -1;
s.top1=max;
}
void teststack() {
sqstack s;
inidestack(s);
//...
}
如果top0+1=top1,那么共享栈已满