1、线性表的单链表表示
链式存储线性表时,不需要使用地址连续的存储单元,即不要求逻辑上相邻的元素在物理位置上也相邻,它通过“链”建立起来数据元素之间的逻辑关系,因此插入和删除操作不需要移动元素,而只需要修改指针,但也会失去顺序表可随机存取的优点。
2、单链表的基本操作
函数 | 说明 |
---|---|
void InitList(LinkList &L); | //初始化顺序表 |
int Length(LinkList &L); | //返回当前长度; |
bool Empty(LinkList &L); | //判断是否为空 |
void DestoryList(LinkList &L); | //销毁单链表,头结点也销毁 |
void PrintList(LinkList &L); | //按前后顺序输出线性表L的所有元素值 |
bool ListInsert(LinkList L, int index, LNode *e); | //插入指定位置结点 |
bool Delete_Node(LNode *e); | //删除指定结点 |
bool Delete_IndexNode(LinkList &L,int index); | //删除指定位置结点 |
bool insert_TailNode(LNode *node, LNode *p); | //按值查找结点 |
LNode *GetElem(LinkList &L, int index); | //按位查找结点 |
bool insert_HeadNode(LNode *node, LNode *p); | //对结点进行前插操作 |
LNode *Init_Node(int e); | //根据元素值构造新的结点 |
3、代码
①LinkList.h
#include<stdio.h>
#include<stdlib.h>
//带头结点的单链表
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
//初始化顺序表
void InitList(LinkList &L);
//返回当前长度;
int Length(LinkList &L);
//判断是否为空
bool Empty(LinkList &L);
//销毁单链表,头结点也销毁
void DestoryList(LinkList &L);
//按前后顺序输出线性表L的所有元素值
void PrintList(LinkList &L);
//插入指定位置结点
bool ListInsert(LinkList L, int index, LNode *e);
//删除指定结点
bool Delete_Node(LNode *e);
//删除指定位置结点
bool Delete_IndexNode(LinkList &L,int index);
//按位查找结点
LNode *GetElem(LinkList &L, int index);
//按值查找结点
LNode *LocateElem(LinkList &L, int e);
//对结点进行后插操作
bool insert_TailNode(LNode *node, LNode *p);
//对结点进行前插操作
bool insert_HeadNode(LNode *node, LNode *p);
//根据元素值构造新的结点
LNode *Init_Node(int e);
②LinkList.cpp
#include"LinkList.h"
//头插法建立单链表
//插入50个数据
LinkList List_HeadInsert(LinkList &L) {
LNode *s;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
for (int i = 1; i <=50; i++) {
s = (LNode*)malloc(sizeof(LNode));
s->data = i;
s->next = NULL;
s->next = L->next;
L->next = s;
}
return L;
}
//尾插法建立单链表
//插入50个数据
LinkList List_TailInsert(LinkList &L) {
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
LNode *s,*r=L;
for (int i = 1; i <= 50; i++) {
s = (LNode*)malloc(sizeof(LNode));
s->data = i;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
//初始化单链表
void InitList(LinkList &L) {
//测试采用尾插法
List_TailInsert(L);
}
//返回单链表当前长度;
int Length(LinkList &L) {
if (L == NULL) {
return 0;
}
int length = 0;
while (L->next != NULL) {
L = L->next;
length++;
}
return length;
}
//判断链表是否为空
bool Empty(LinkList &L) {
if (L==NULL||L->next == NULL)
return true;
else return false;
}
//销毁单链表,头结点也销毁
void DestoryList(LinkList &L) {
if (L == NULL) {
return;
}
LNode *p;
while (L) {
p = L;
L = L->next;
free(p);
}
L = NULL;
}
//清空单链表,还剩下头结点
void ClearList(LinkList &L) {
if (L == NULL) {
return;
}
LNode *p=L->next,*q;
while (p) {
q = p->next;
free(p);
p = q;
}
L->next = NULL;
}
//按前后顺序输出线性表L的所有元素值
void PrintList(LinkList &L) {
if (L== NULL) {
return;
}
LNode *p=L->next;
if (p == NULL)
return;
for (int i = 1; p != NULL; i++){
printf("第%d个值为%d\n", i, p->data);
p = p->next;
}
}
//插入指定位置结点
bool ListInsert(LinkList L, int index, LNode *e) {
if (index == 0) {
return false;
}
LNode * p=GetElem(L, index - 1);
if (p == NULL) {
return false;
}
e->next = p->next;
p->next = e;
return true;
}
//对结点进行后插操作
bool insert_TailNode(LNode *node, LNode *p) {
if (node == NULL) {
return false;
}
p->next = node->next;
node->next = p;
return true;
}
//对结点进行前插操作,通过交换数据
bool insert_HeadNode(LNode *node, LNode *p) {
if (node == NULL||p==NULL) {
return false;
}
p->next = node->next;
node->next = p;
int k = node->data;
node->data = p->data;
p->data = k;
return true;
}
//删除指定结点
//这里使用简便方法删除,通过交换双方的数据
bool Delete_Node(LNode *e) {
if (e->next == NULL) {
free(e);
return true;
}
else {
LNode *p = e->next;
e->data = p->data;
e->next = p->next;
free(p);
return true;
}
}
//删除指定位置结点
bool Delete_IndexNode(LinkList &L, int index) {
if (index <= 0) {
return false;
}
int i = 1;
LNode *r = L->next;
while (r != NULL && i < index) {
r = r->next;
i++;
}
return Delete_Node(r);
}
//按位查找结点
LNode *GetElem(LinkList &L, int index){
if (index == 0)
return L;//返回头结点
LNode *p = L->next;
int i = 1;
while (p!= NULL && i < index) {
p = p->next;
i++;
}
return p;
}
//按值查找结点
LNode *LocateElem(LinkList &L, int e){
if (L == NULL)
return NULL;
LNode *p = L->next;
while (p != NULL && p->data != e) {
p = p->next;
}
return p;
}
//根据元素值构造新的结点
LNode *Init_Node(int e) {
LNode *node = (LNode*)malloc(sizeof(LNode));
node->data = e;
node->next = NULL;
return node;
}
③main函数
//单链表的测试代码
void LinkList_Test() {
LinkList L;
//初始化单链表
InitList(L);
LNode*p=Init_Node(51);
//插入指定位置结点
ListInsert(L, 1, p);
//删除指定位置结点
Delete_IndexNode(L,1);
//对接点进行前插操作
p = Init_Node(51);
insert_HeadNode(L->next,p);
//对结点进行后差操作
p = Init_Node(50);
insert_TailNode(L, p);
//输出结果
PrintList(L);
//按位查找结点
int index = 50;
LNode*node=GetElem(L,index);
printf("查找的结点序号为:%d,值为:%d\n", index, node->data);
int length = Length(L);
printf("当前单链表长度为:%d\n", length);
//销毁单链表
DestoryList(L);
printf("销毁单链表");
length = Length(L);
printf("当前单链表长度为:%d\n", length);
}
//主函数
int main() {
LinkList_Test();
system("pause");
return 0;
}
4、输出结果