目录
一、顺序表
(1)静态分配
#define MaxSize 50
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];
int length;
}SqList;
(2)动态分配
#define InitSize 100 //初始定义的长度
typedef int ElemType;
typedef struct {
ElemType *data; //指向连续空间的第一个ele
int MaxSize,length; //最大长度和当时长度
}SeqList;
(3)基本操作
1)初始化
//静态分配初始化
void InitList(SqList &L){
L.length = 0;
}
直接令length=0,不可省略
此处可以初始化值,else会被内存中曾经使用过此处内存的脏data影响,but此步骤可以省略
reason:遍历时是i到length-1,so初始化length即可,不会读取到后面的脏data
//动态分配初始化
void InitList(SeqList &L){
L.lenth = 0;
L.MaxSize = InitSize;
L.data = (ElemType*)malloc(MaxSize * sizeof (SeqList));
}
初始化表长度和最大长度,指针开辟新空间,指向第一个位置
2)动态扩展空间
当顺序表满了之后,定义一个新的指针指向原顺序表,原顺序表的data指针在内存中申请新的一段大的连续的空间,再将原来顺序表拷贝到新的顺序表中,释放新指针
void IncreaseSize(SeqList &L,int len){ //len表示增加的长度
ElemType *L2 = L.data;//SeqList的第一个ele地址
L.data = (ElemType *) malloc(sizeof(ElemType)*(MaxSize+len));
for (int i = 0; i < MaxSize; ++i) {
L.data[i]=L2[i];
}
L.MaxSize = L.MaxSize + len;
free(L2);
}
attn:①静态arr和动态arr都有MaxSize,含义不同,静态arr中是常量,不可更改;动态arr中是SeqList的属性,可以更改
②一开始MaxSize是初始化定义的InitSize,表示最初定义的顺序表最大长度
③i<MaxSize 《==》i<L.length ∵此时 MaxSize == L.length
④SeqList的MaxSize需要+len
3)插入
在L的第i个位置插入元素e
bool提示是否插入成功
bool ListInsert(SqList &L,int i,ElemType e){//i为位序
if(i<1 || i>L.length+1){//超出范围,ele得挨着
return false;
}
if(L.length +1 >MaxSize){//表满了
return false;
}
int j;
for (j = L.length; j >= i ; j--) {
L.data[j-1] = L.data[j];
}
L.data[i-1] = e;
L.length++;//attn
return true;
3)删除
删除L中第i个位置的ele,用e保存
bool ListDelete(SqList &L,int i ,ElemType &e){
if(i<1 || i>L.length){//出界
return false;
}
e = L.data[i-1];//保存
for (int j = i; j <L.length ; j++) {
L.data[j-1]= L.data[j];
}
L.length--;
return true;
}
二.单链表(带头结点)
初始不考察不带头结点的单链表,so此处仅展示带头结点的单链表
1.定义结构体
typedef int ElemType;
typedef struct LNode {
ElemType data; //数据域
struct LNode *next;//指针域
} LNode, *LinkList;
2.初始化
bool InitList(LinkList &L){
L = (LNode *) malloc(sizeof(LNode));//申请空间
L = NULL;//空链表
return true;
}
3.判空and求表长
bool isEmpth(LinkList L){
return L->next;
}
int Length(LinkList L) {
LinkList p = L;
int len = 0;
while (NULL != p->next) {
p = p->next;
len++;
}
return len;
}
4.查找元素
(1)按位序
LNode *GetElem(LinkList L, int i) {
LNode *p;
p = L;
int j = 0;
while (NULL != p && j < i) {
p = p->next;
j++;
}
return p;
}
(2)按值
当p指向元素的值==e,停止
LNode* LocationElem(LinkList L,ElemType e){
LNode *p =L;
while(NULL != p->next && p->data != e){
p=p->next;
}
return p;
}
5.插入元素
(1)指定结点的后插操作
在L的第i个位置插入e
之后找到第i-1个元素的位置,在该ele后插入
bool ListInsert(LinkList &L, int i, ElemType e) {
if (i < 1) return false;//i范围不合法
LNode *p;
LNode *s = (LNode *) malloc(sizeof(LNode));
p = L;
int j = 0;
while(NULL != p && j<i-1 ){
p=p->next;
j++;
}
if(NULL == p) return false;//超出范围了
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
结合之前学习的:查找第i-1个元素
//观察
//按位序
LNode *GetElem(LinkList L, int i) {
LNode *p;
p = L;
int j = 0;
while (NULL != p && j < i) {
p = p->next;
j++;
}
return p;
}
汇总
//so
bool ListInsert(LinkList &L, int i, ElemType e) {
if (i < 1) return false;//i范围不合法
LNode *p;
LNode *s = (LNode *) malloc(sizeof(LNode));
p = GetElem(LinkList L, int i-1);
if(NULL == p) return false;//超出范围了
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
(2)指定结点的前插操作
step1:判断i是否合法
step2:找到第i个ele
step3:先将第i个ele 的data保存到新结点中,再将第i个ele 的data赋予e,再进行链接
bool ListPerInsert(LinkList L, int i, ElemType e) {
LNode *p = L;
if (i < 1) return false;
int j = 0;
while (p != NULL && j < i) {
p = p->next;
j++;
}
LNode *s = (LNode *) malloc(sizeof(LNode));
if(s == NULL) return false; //内存分配失败
s->next = p->next;
s->data = p->data;
p->data = e;
p->next = s;
return true;
}
6.删除
(1)按指定结点
bool ListDelete(LinkList &L,int i,ElemType &e){
if(i<1) return false;
LNode *p;
p = L;
int j = 0;
while (NULL != p && j < i-1) {
p = p->next;
j++;
}
if(NULL == p || p->next == NULL) return false;
LNode *q = p->next;
e = q->data;
p->next = q->next;
free(q);
return true;
}
(2)替换技巧
bool ListDeleteRePlace(LinkList &L, int i, ElemType e) {
if (i < 1) return false;
LNode *p = L;
int j = 0;
while (NULL != p && j < i) {
p = p->next;
}
if (p == NULL) return false;
LNode *s = p->next;
p->data = s->data;
p->next = s->next;
free(s);
return true;
}
7.单链表的建立
(1)尾插法
用一个指针指向尾结点,执行后插操作
LinkList ListTailInsert(LinkList &L) {
L = (LNode*) malloc(sizeof(LNode));
L->next=NULL;
LNode *p = L;
ElemType e;
e = scanf("%d", &e);
while (e != 9999) {
LNode *s = (LNode *) malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
p = p->next;
scanf("%d", &e);
}
return L;
}
(2)头插法
用一个指针指向头结点,执行后插操作
LinkList ListHeadInsert(LinkList &L){
L = (LNode*) malloc(sizeof(LNode));
L->next=NULL;
ElemType e;
e = scanf("%d", &e);
LNode *s;
while (e != 9999) {
s = (LNode *) malloc(sizeof(LNode));
s->data = e;
s->next = L->next;
L->next = s;
scanf("%d", &e);
}
return L;
}
三、双链表
1.初始化
bool InitLinkList(DLinkList &L) {
L = (DNode *) malloc(sizeof(DNode));
L->next = NULL;
L->prior = NULL;
return true;
}
2.插入(后插)
在第i个位置插入元素e
查找第i个位置+后插
bool DLinkListInsert(DLinkList &L, int i, ElemType e) {
if (i < 1) return false;
DNode *p = L, *q, *s;
s = (DNode *) malloc(sizeof(DNode));
s->data = e;
int j = 0;
while (NULL != p && j < i - 1) {
p = p->next;
}
if (p == NULL) return false;
q = p->next;
s->next = q;
s->prior = p;
q->prior = s;
p->next = s;
return true;
}
3.删除(后删)
bool DeleteNextNode(DNode *p){
if (p == NULL) return false;
DNode *q=p->next;
q = p->next;
if(q->next!=NULL)//q不是最后一个结点
q->next->prior = p;
p->next = q->next;
free(q);
return true;
}
4.遍历
(1)前向遍历
while(p!=NULL){
p = p->prior;
}
//跳过头结点
while(p->prior!=NULL){
p = p->prior;
}
(2)后向遍历
while (p != NULL) {
p->next = p;
}
(4)查找
1)按值查找
2)按位查找
四、循环链表
1.循环单链表
(1)操作
1)初始化
bool ListInit(LinkList &L) {
L = (LNode *) malloc(sizeof(LNode));
if(L==NULL) return false;//内存不足
L->next = L;
return true;
}
2)判空
bool isEmpty(LinkList L){
return (L->next == L);
}
3)判头
bool isHead(LNode* p){
return p == L->next;
}
4)判尾
bool isTail(LNode* p){
return NULL == p->next;
}
5)插入删除
2.循环双链表
(1)操作
1)初始化
bool DLinkListInit(DLinkList &L){
L = (LNode *) malloc(sizeof(DNode));
if(L==NULL) return false;//内存不足
L->next = L;
L->prior =L;
return true;
}
2)判空
bool isEmpty(DLinkList L){
return L->next == L;
}
3)判头
bool isHead(DNode* p){
return p->prior == L;
}
4)判尾
bool isTail(DNode* p){
return p->next == L;
}