(二)代码定义
1.初步代码
struct LNode {//结点
ElemType data;
struct LNode *next;
};
2.新增结点
struct LNode {//结点
ElemType data;
struct LNode *next;
};
struct LNode *p=(struct LNode *)malloc(sizeof(struct LNode));
简化:将struct LNode定义为LNode
struct LNode {//结点
ElemType data;
struct LNode *next;
};
typedef struct LNode LNode;//将struct LNode定义为LNode
LNode* p = (LNode*)malloc(sizeof(LNode));//简化
3.进一步简化
struct LNode {//结点
ElemType data;
struct LNode *next;
};
typedef struct LNode LNode;//将struct LNode定义为LNode
typedef struct LNode *LinkList;//将struct LNode *定义为LinkList
即
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
因此 LNode *L 等价于 LinkList L
更多的,使用
LinkList表示单链表,用LNode *表示结点
(三)基本操作1
1.带头结点的单链表,初始化与判空
#include<stdlib.h>
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool InitList(LinkList &L) {//初始化
L = (LNode*)malloc(sizeof(LNode));//头指针L指向无数据的头结点
if (L == NULL)//内存不足,分配失败
return false;
L->next = NULL;//头结点的next指针域设为NULL
return true;
}
bool Empty(LinkList L) {//判空
if (L->next == NULL)
return true;
else
return false;
}
void test() {
LinkList L;//创建单链表L
InitList(L);//初始化
Empty(L);//判空
}
2.不带头结点的单链表,初始化与判空
#include<stdlib.h>
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool InitList(LinkList &L) {//初始化
L = NULL;
return true;
}
bool Empty(LinkList L) {//判空
if (L == NULL)
return true;
else
return false;
}
void test() {
LinkList L;//创建单链表L
InitList(L);//初始化
Empty(L);//判空
}
(四)基本操作2
1.头插法建立单链表
#include<stdlib.h>
#include<stdio.h>
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
LinkList List_HeadInsert(LinkList &L) {
LNode *s;//工作指针
int x;//要插入的值
L = (LinkList)malloc(sizeof(LNode));//创建头结点
L->next = NULL;
scanf("%d", &x);
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));//s指向新结点
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d", &x);
}
return L;
}
每个结点插入的时间复杂度O(1),设单链表长n,则总时间复杂度O(n)
2.尾插法建立单链表
#include<stdlib.h>
#include<stdio.h>
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
LinkList List_TailInsert(LinkList &L) {
LNode *s;//工作指针
LNode *r = L;//r做为表尾指针
int x;
L = (LinkList)malloc(sizeof(LNode));
scanf("%d", &x);
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL;
return L;
}
时间复杂度O(n)
3.按序号查找
#include<stdlib.h>
#include<stdio.h>
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
LNode *GetElem(LinkList L, int i) {
int j = 0;//0号位是头结点
LNode *p = L;//p指向头结点
/*以上两行也可写为
int j=1;//从第一个结点开始
LNode *p=L->next;//p指向第一个结点
*/
if (i == 0)
return L;//0号是头结点,返回
if (i < 1)
return NULL;
while (p && j < i) {
p = p->next;
j++;
}
return p;
}
时间复杂度O(n)
4.按值查找
#include<stdlib.h>
#include<stdio.h>
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
LNode* LocateElem(LinkList L, ElemType e) {
LNode *p=L->next;
while (p!=NULL&&p->data!=e) {
p = p->next;
}
return p;
}
时间复杂度O(n)
5.按位序插入(带头结点)
#include<stdlib.h>
#include<stdio.h>
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool ListInsert(LinkList &L, int i, ElemType e) {
//在第i个位置插入元素e
if (i < 1)
return false;
LNode *p=L;//p指向头结点
int j = 0;//从0号位的头结点开始
while (p != NULL &&j < i - 1) {
p = p->next;
j++;
}
if (p == NULL) {
return false;
}
LNode *s = (LNode*)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
平均时间复杂度O(n)
6.按位序插入(不带头结点)
#include<stdlib.h>
#include<stdio.h>
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
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 true;
}
LNode *p=L;//p指向第一个结点
int j = 1;
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
if (p == NULL)
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));
s->data=e;
s->next = p->next;
p->next = s;
return true;
}
7.指定结点前插
(1)传入要插入元素
bool InsertPriorNode(LNode* p, ElemType e) {
if (p == NULL)
return false;
LNode *s = (LNode*)malloc(sizeof(LNode));
if (s == NULL)
return false;
s->next = p->next;//p当前结点,s新结点
p->next = s;
s->data = p->data;
p->data = e;
return true;
}
(2)传入结点
bool InsertPriorNode(LNode* p, LNode *s) {
if (p == NULL||s==NULL)
return false;
s->next = p->next;//p当前结点,s新结点
p->next = s;
ElemType temp = p->data;//存储p的数据
p->data = s->data;
s->data = temp;
return true;
}
8.按位删除(带头结点)
bool ListDelete(LinkList &L, int i, ElemType &e) {
if (i < 1)
return false;
LNode *p=L;
int j = 0;
while (p != NULL && j < i - 1) {
p = p->next;
j++;
}
if (p == NULL)
return false;
if (p->next == NULL)
return false;//p已经是最后一个结点,无法完成删除
LNode *q = p->next;
e = q->data;
p->next = q->next;
free(q);
return true;
}
typedef struct DNode {
ElemType data;
struct DNode *prior, *next;
}DNode,DLinklist;
2.初始化
typedef struct DNode {
ElemType data;
struct DNode *prior, *next;
}DNode,*DLinklist;
bool InitDLinkList(DLinklist &L) {
L=(DNode*)malloc(sizeof(DNode));
if (L == NULL)
return false;
L->prior = NULL;
L->next = NULL;
return true;
}
void testDLinklist() {
DLinklist L;
InitDLinkList(L);
}
3.判空
bool Empty(DLinklist L) {
if (L->next == NULL)
return true;
else
return false;
}
4.插入
bool InsertNextDNode(DNode *p, DNode *s) {
//p当前,s新
s->next = p->next;
if(p->next!=NULL)
p->next->prior = s;
s->prior = p;
p->next = s;
}

5.删除

bool DeleteNextDNode(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;
}
bool DestoryList(DLinklist &L) {//销毁双链表
while (L->next != NULL) {//依次删除头结点的后继结点
DeleteNextDNode(L);
}
free(L);
L = NULL;
}

1.循环单链表

(1)初始化
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
bool InitList(LinkList &L) {
L = (LNode*)malloc(sizeof(LNode));
if (L == NULL)
return false;
L->next = L;
return true;
}
(2)判空
L->next=L
(3)判断结点p是否为循环单链表的表尾结点
p->next=L
2.循环双链表

(1)初始化
typedef struct DNode {
ElemType data;
struct DNode *next,*prior;
}DNode,*DLinkList;
bool InitDList(DLinkList &L) {
L = (DNode*)malloc(sizeof(DNode));
if (L == NULL)
return false;
L->prior = L;
L->next = L;
return true;
}
(2)判空
L->next=L
(3)判断结点p是否为循环双链表的表尾结点
p->next=L
(4)插入
bool InsertNextDNode(DNode *p,DNode *s){
//s是新结点,p是当前结点
s->next = p->next;
p->next->prior = s;
s->next = p;
p->prior = s;
}
(5)删除
bool DeleteDNode(DNode *p){
//p是q的前驱结点,要删除后面的q
DNode *q = p->next;
if (q == NULL)
return false;
p->next = q->next;
q->next->prior = p;
free(q);
}
1.特点
(1)优点:增、删操作不需要大量移动元素
(2)缺点:不能随机存取,只能从头结点开始依次查找,容量固定不可变

2.代码
#define MaxSize 10
struct Node {
ELemType data;
int next;
};
void testSLinkList() {
struct Node a[MaxSize];
}
即
#define MaxSize 10
struct Node {
ELemType data;
int next;
};
typedef struct Node SLinkList[MaxSize];
void testSLinkList() {
SLinkList a;//用SLinkList定义一个长度为MaxSize的Node型数组
}
即
#define MaxSize 10
typedef struct {
ElemType data;
int next;
}SLinkList[MaxSize];
void testSLinkList() {
SLinkList a;
}