以“结点的序列”表示线性表称作
线性链表(单链表)
单链表是链式存取的结构,为找第 i 个数据元素,必须先找到第 i-1 个数据元素。
因此,查找第 i 个数据元素的基本操作为:移动指针,比较 j 和 i
单链表
1、链接存储方法
链接方式存储的线性表简称为链表(Linked List)。
链表的具体存储表示为:
① 用一组任意的
存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为
指针(pointer)或链(link))
注意:
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
2、链表的结点结构
┌───┬───┐
│data │next │
└───┴───┘
data域--存放结点值的数据域
next域--存放结点的直接后继的地址(位置)的
指针域(链域)
注意:
①链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的。
②每个结点只有一个链域的链表称为单链表(Single Linked List)。
3、头指针head和终端结点指针域的表示
单链表中每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始结点。
注意:
链表由头
指针唯一确定,单链表可以用头指针的名字来命名。
终端结点无后继,故终端结点的指针域为空,即NULL。
4、单链表的一般图示法
由于我们常常只注重结点间的逻辑顺序,不关心每个结点的实际位置,可以用箭头来表示链域中的指针,线性表(bat,cat,fat,hat,
jat,lat,mat)的单链表就可以表示为下图形式。
5、单链表类型描述
typedef char DataType; //假设结点的数据域类型为字符
typedef struct node{ //结点类型定义
DataType data; //结点的数据域
struct node *next;//结点的
指针域
}ListNode;
typedef ListNode *LinkList;
ListNode *p;
LinkList head;
注意:
①LinkList和ListNode是不同名字的同一个指针类型(命名的不同是为了概念上更明确)
②*LinkList类型的
指针变量head表示它是单链表的头指针
③ListNode类型的指针变量p表示它是指向某一结点的指针
SListNode.h
#ifndef __SLISTNODE_H__
#define __SLISTNODE_H__
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
typedef struct SListNode
{
DataType data;
struct SListNode* next;
}SListNode;
SListNode* BuyNode(DataType x);//申请节点
void PrintSlist(SListNode* pHead);//打印链表
void InitSList(SListNode*& pHead);//初始化链表
void PushBack(SListNode*& pHead, DataType x);//尾插
void PopBack(SListNode*& pHead);//尾删
void PushFront(SListNode*& pHead, DataType x);//前插
void PopFront(SListNode*& pHead);//头删
void Insert(SListNode*& pHead, SListNode*& pos, DataType x);//在pos前插入一个数据
void Erase(SListNode*& pHead, SListNode* pos);//删除指定位置
void Remove(SListNode*& pHead, DataType x);//删除x
SListNode* Find(SListNode*& pHead, DataType x);//寻找x
void DestoryList(SListNode*& pHead);//销毁
#endif;//__SEQLIST_H__
SListNode.c
#include"SListNode.h"
SListNode* BuyNode(DataType x)//申请节点
{
SListNode *node = (SListNode*)malloc(sizeof(SListNode));
node->data = x;
node->next = NULL;
return node;
}
void PrintSlist(SListNode* pHead)//打印链表
{
SListNode *cur = pHead;//链表最后一项为NULL=0
while (cur)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
void InitSList(SListNode*& pHead)//初始化链表
{
assert(pHead);
pHead = NULL;
}
void PushBack(SListNode*& pHead, DataType x)//尾插
{
assert(pHead);
if (pHead == NULL)
{
pHead = BuyNode(x);
}
else
{
SListNode* cur = pHead;
while (cur->next)
{
cur = cur->next;
}
cur->next = BuyNode(x);
}
}
void PopBack(SListNode*& pHead)//尾删
{
assert(pHead);
//没有节点
if (pHead == NULL)
{
printf("The List is empty\n");
return;
}
//一个节点
else if (pHead->next == NULL)
{
free(pHead);
pHead = NULL;
}
//多个节点
else
{
SListNode *prev = NULL;
SListNode *cur = NULL;
cur = pHead;
while (cur->next)
{
prev = cur;
cur = cur->next;
}
free(cur);
prev->next = NULL;
}
}
void PushFront(SListNode*& pHead, DataType x)//前插
{
assert(pHead);
if (pHead == NULL)
{
pHead = BuyNode(x);
}
else
{
SListNode* tmp = BuyNode(x);
tmp->next = pHead;
pHead = tmp;
}
}
void PopFront(SListNode*& pHead)//头删
{
assert(pHead);
//没有节点
if (pHead == NULL)
{
printf("The List is empty\n");
return;
}
//other
else if (pHead->next == NULL)//判断是否只有一个节点
{
free(pHead);
pHead = NULL;
}
else//多个节点,next接收pHead的值,防止释放后找不到后面的链表
{
SListNode* next = pHead->next;
free(pHead);
pHead = next;
}
}
void Insert(SListNode*& pHead, SListNode*& pos, DataType x)//在pos前插入一个数据
{
assert(pos);
assert(pHead);
if (pos == pHead)
{
PushFront(pHead, x);
}
else
{
SListNode* prev = NULL, *cur = NULL;
cur = pHead;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
SListNode* tmp = BuyNode(x);
tmp->next = cur;
prev->next = tmp;
}
}
void Erase(SListNode*& pHead, SListNode* pos)//删除指定位置
{
assert(pos);
assert(pHead);
if (pos == pHead)
{
PopFront(pHead);
}
else if (pHead->next == NULL)
{
SListNode* prev = NULL, *cur = NULL;
cur = pHead;
while (cur->next)
{
prev = cur;
cur = cur->next;
}
free(cur);
prev->next = NULL;
}
else
{
SListNode* prev = NULL, *cur = NULL;
cur = pHead;
while (cur != pos)
{
prev = cur;
cur = cur->next;
}
prev->next = cur->next;
free(cur);
}
}
void Remove(SListNode*& pHead, DataType x)//删除x
{
if (pHead == NULL)//判断是否为空链表
{
printf("The List is empty\n");
return;
}
else if (pHead->data == x)
{
SListNode* next = pHead->next;
free(pHead);
pHead = next;
}
else
{
SListNode* prev = NULL, *cur = NULL;
cur = pHead;
while (cur->data != x)
{
prev = cur;
cur = cur->next;
}
prev->next = cur->next;
free(cur);
}
}
SListNode* Find(SListNode*& pHead, DataType x)//寻找x
{
SListNode* cur = pHead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void DestoryList(SListNode*& pHead)//销毁
{
SListNode* cur = pHead;
while (cur)
{
SListNode* tmp = cur;
cur = cur->next;
free(tmp);
tmp = NULL;
}
}