单链表
定义单链表结点类型
struct LNode{
ElemType data; //数据域
struct LNode * next //指针指向下一个节点
};
增加一个新结点:在内存中申请一个结点所需空间,并用指针p指向这个结点
struct LNode * p = (struct *) malloc (sizeof(struct LNode));
ps:
struct写的很麻烦,所以可以用typedef,
typedf <数据类型><小名>
typedef int zhengshu;
typedef int * zhengshuzhizhen
zhengshu x = 1//int x = 1 ;
zhengshuzhizhen * p//int * p;
所以增加一个新结点就可以写成
typedef struct LNode LNode;
LNode * p = (LNode *) malloc (seizeof(LNode));
但是这还不够简洁
课本中是这样写的
typedef struct LNode {
ElemType data; //数据域
struct LNode * next //指针指向下一个节点
}LNode, * LinkList;
其实相当于
struct LNode{
ElemType data; //数据域
struct LNode * next //指针指向下一个节点
};
typedef struct LNode LNode;
typedef struct LNode * LinkList;
把struct LNode重命名为LNode
并且用LinkList来表示这是一个指向LNode的指针
要表示一个单链表是,只需要声明一个头指针L,指向单链表第一个结点(找到第一个结点,就相当于找到整个单链表)
LNode *L;//声明一个指向单链表第一个结点的指针
或
LinkList L//声明一个指向单链表第一个结点的指针
这两种表现方式作用是一样的,但是强调这是一个单链表用LinkList,强调这是一个结点用LNode *。
不带头结点的单链表
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef struct {
ElemType data; //数据域
struct LNode * next //指针指向下一个节点
}LNode, * LinkList;
//初始化一个空的表
bool InitList(LinkList &L) {
L = NULL; //空表,暂时没有任何结点(防止脏数据)
return true;
}
void test(){
LinkList L;//声明一个指向单链表的指针
InitList(L)
}
//判断单链表是否为空
bool Empty(LinkList L){
return (L == NULL);
}
带头结点的单链表
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef struct {
ElemType data; //数据域
struct LNode * next //指针指向下一个节点
}LNode, * LinkList;
//初始化一个空的表
bool InitList(LinkList &L) {
L = (LNode *) malloc (sizeof(LNode)); //分配一个头结点
if (L == NULL)
return false;
L -> next= NULL;
return true;
}
void test(){
LinkList L;//声明一个指向单链表的指针
InitList(L)
}
//判断单链表是否为空
bool Empty(LinkList L){
if(L->next == NULL)
return true;
else
return false;
}
按位序插入
bool ListInsert(LinkList &L, int i, ElemType e ){
if(i<1)
return false;
LNode * p; //指针p指向当前扫描到的结点
int j = 0; //记录当前p指向的是第几个结点
P = L; //L指向头结点,头结点是第0个结点
while (p != NULL && j < i-1 ){//循环到第i-1个结点
p = p->next;
j++;
}
if(p == NULL) //p值不合法
return false;
LNode * s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
指定结点的后插操作
bool InserNextNode (LNode * p, ElemType e){
if (p == NULL)
return false;
LNode * s = (LNode *)malloc(sizeof(LNode));
if(s == NULL) //内存分配失败,计算机被榨干
retuen false; //一般不会出现,只是有可能
s->data = e; //用结点s保存要插入的数据元素e
s->next = p ->next;
p -> next = s;
return true;
}
指定结点前插(这个牛)
bool InserPriorNode(LNode * p, ElemType e){
if (p == NULL)
return false;
LNode * s = (LNode *)malloc(sizeof(LNode));
if(s == NULL)
retuen false;
s->next = p->next;
p->next = s; //新结点s连到p之后
s->data = p->data; //将p中元素复制到s中
p->data = e; //p中元素覆盖为e
return true;
}
按位序删除
bool ListDelete(LinkList &L, int i, ElemType &e ){
if(i<1)
return false;
LNode * p; //指针p指向当前扫描到的结点
int j = 0; //记录当前p指向的是第几个结点
P = L; //L指向头结点,头结点是第0个结点
while (p != NULL && j < i-1 ){//循环到第i-1个结点
p = p->next;
j++;
}
if(p == NULL) //p值不合法
return false;
if(p->next == NULL) //第i-1个结点之后已无其他结点
LNode * q = p->next //令q指向被删除结点
e = q->data; //用e返回元素的值 &
p->next = q->next; //将*q结点从链中断开
free (q); //释放
return true;
}