链表是学习数据机构必须要掌握的知识,它是学习复杂数据结构的基础,如:二叉树,图等
理解几个常用术语:
1、首节点:第一个有效节点
2、尾节点:最后一个有效节点
3、头节点:没有存放有效数据,没有存放节点个数;设置头节点是因为对链表操作的时候,加上一个没有实际含义的头节点方便我们操作
4、头指向节点:指向头的节点
5、尾指向节点:指向尾的节点
一、链表的定义:
1、多个节点离散存储
2、彼此通过node(节点)相连
3、每个节点只有一个前驱节点,只有一个后续节点
4、首节点没有前驱节点,尾节点没有后续节点(循环链表除外)
先看一张图
根据上面的图,我们定义一个单向链表的节点Node
#include <stdio.h> // C语言
typedef struct node
{
int data; // 有效数据
struct node *pNext; // 指针数据,尾节点
}Node, *pNode;
class Node // PHP版
{
private $Data;//节点数据
private $Next;//下一节点
public function setData($value){
$this->Data=$value;
}
public function setNext($value){
$this->Next=$value;
}
public function getData(){
return $this->Data;
}
public function getNext(){
return $this->Next;
}
public function __construct($data,$next){
$this->setData($data);
$this->setNext($next);
}
}
list{} // lua
function list:new()
local l = { data = nil, next = nil }
setmetatable(l, self)
self.__index = self
return l
end
二、创建一个单向链表
我们将节点创建好之后,就可以把多个节点连接起来,链表就创建好了
1、创建头节点
pNode pHead = NULL;
pHead = createlink(4); //创建一个链表,有4个节点
traverslink(pHead); //遍历链表
2、链表的具体实现
pNode createlink(int len)
{
int i;
int val = 1; // 值
pNode pHead = (pNode)malloc(sizeof(Node)); // 分配内存
if (NULL == pHead)
{
exit(-1); // 失败退出
}
pNode pWei = pHead;
pWei->pNext = NULL; // 永远处于尾节点
for (i = 0; i < len; i++)
{
val = val + i;
pNode pNew = (pNode)malloc(sizeof(Node));
if (NULL == pNew)
{
exit(-1); // 分配内存失败,退出
}
pNew->data = val;
pWei->pNext = pNew;
pNew->pNext = NULL;
pWei = pNew;
}
return pHead; // 返回头节点
}
void traverslink(pNode pHead) // 遍历
{ // 遍历非常简单,直接使用连接的节点
pNode p = pHead->pNext;
while (NULL != p)
{
printf("%d ", p.data);
p = p->pNext;
}
printf("\n");
}
下面是PHP和Lua创建链表和遍历链表
class LinkList { // PHP版,这里我们只需要设置头节点就可以了,然后根据头节点新增、插入...
private $header;//头节点
public function setHeader($value){
$this->header=$value;
}
public function getHeader(){
return $this->header;
}
public function __construct(){
$this->setHeader(new Node(null,null)); //设置头节点
}
//遍历节点
public function get()
{
$node=$this->header;
if($node->getNext()==null){
print("数据集为空!");
return;
}
while($node->getNext()!=null)
{
print($node->getNext()->getData());
if($node->getNext()->getNext()==null){break;}
$node=$node->getNext();
}
}
}
function list:lprint() // lua遍历链表,这里不需要创建链表,在我们设置节点的时候直接调用就创建了
local l = self
while l.next do
print(l.data)
l = l.next
end
end
4、链表新增好之后,就可以实现判断是否为空,新增,删除..
BOOL isEmpty(pNode pHead) // 在C语言中是没有Bool类型的,只能使用宏定义使用
{
if (NULL == pHead->pNext)
return TRUE;
else
return FALSE;
}
int length(pNode pHead)
{
int len = 0;
pNode p = pHead->pNext;
while (NULL != p)
{
p = p->pNext;
len = len + 1;
}
return len;
}
BOOL insert(pNode pHead, int pos, int val)
{
int i = 0;
pNode p = pHead;
while (NULL !=p && i<pos-1)
{
p = p->pNext;
++i;
}
if (i > pos-1 || NULL == p)
return FALSE;
pNode pNew = (pNode)malloc(sizeof(Node));
pNew->data = val;
pNode q = p->pNext;
p->pNext = pNew;
pNew->pNext = q;
return TRUE;
}
BOOL delete(pNode pHead, int pos, int *pVal)
{
int i = 0;
pNode p = pHead;
while (NULL !=p && i<pos-1)
{
p = p->pNext;
++i;
}
if (i > pos-1 || NULL == p)
return FALSE;
pNode q = p->pNext;
*pVal = q.data;
p->pNext = p->pNext->pNext;
free(q);
q = NULL;
return true;
}
void sort(pNode pHead)
{
int len = length(pHead);
int i, j, t;
pNode p, q;
for (i = 0, p=pHead->pNext; i < len - 1; ++i, p = p->pNext)
{
for(j = j+1, q=p->pNext; j< len; ++j, q=q->pNext)
{
if (p->data > q->data)
{
t = p->data;
p->data = q->data;
q->data = t;
}
}
}
}