1、链式存储结构:在链式存储的过程中,每个元素Node不仅包含元素本身的信息,还包含元素之间的逻辑信息。前驱结点包含后继结点的地址信息(指针域),可以很方便的找到后继结点的位置。
2、链表:通过一组任意的存储单元来存储线性表中的数据元素,由一个个结点构成。
3、单链表:每个结点除包含数据域外,只设置一个指针域,来指向后继结点,这样构成的链表就是单链表。
单链表是一种链式存取的数据结构,用一组任意地址空间(地址空间即存储单元)来存放线性表的数据元素。单链表中的数据是以节点的形式来表示,而节点是用结构体来描述,每个节点都是由元素和指针构成,即该结构体中包含两个成员变量:存放元素的成员变量和存放下一个节点地址的成员变量。单链表的节点结构为如下所示:
4、链表与顺序表的区别:
顺序表的特点为:逻辑相邻的两节点其物理地址也是相邻的;链表的特点为:逻辑相邻的两节点其物理地址不相邻。顺序表的存储方式是:节点元素连续存放在存储单元;链表的存储方式是:节点元素随机存放在存储单元。
5、单链表的结构:
6、单链表的头插
//头插法
bool Insert_head(List plist,int val)
{
Node *p = (Node *)malloc(sizeof(Node)); //p即为新节点
p->data = val; //p的data域设为val
p->next = plist->next; //将plist存储的下一个节点的地址赋值给p
plist->next = p; //将头结点的下一个节点设置为p
return true;
}
7、单链表的尾插
//尾插法
bool Insert_tail(List plist,int val)
{
//第一步,设置新节点
Node *p = (Node *)malloc(sizeof(Node));
assert(p != NULL);
if(p == NULL)
{
return false;
}
p->data = val;
//第二步,找尾节点
Node *q;
for(q = plist;q->next != NULL;q = q->next);
//将p插入到q的后面
p->next = q->next;
q->next = p;
return true;
}
8、完整代码
(1)list.h:
#pragma once
//带头节点的单链表
//单链表尾节点的next为NULL
//List为一条链表;Node *一个节点的地址
typedef struct Node
{
int data; //数据
struct Node *next;//下一个节点的地址
}Node,*List;//List == Node *
//初始化
void InitList(List plist);
//头插法
bool Insert_head(List plist,int val);
//尾插法
bool Insert_tail(List plist,int val);
//在pos下标插入数据val
bool Insert_pos(List plist,int pos,int val);
//查找,找到返回节点地址,没有找到返回NULL
Node *Search(List plist,int key);
//删除第一个key对应的节点
bool Delete(List plist,int key);
//删除第一个数据节点,并通过rtval获得删除的值
bool Delete_head(List plist,int *rtval);
//删除最后一个数据节点,并通过rtval获得删除的值
bool Delete_tail(List plist,int *rtval);
//获取长度,统计数据节点的个数
int GetLength(List plist);
//判空
bool IsEmpty(List plist);
//销毁所有节点
void Destroy(List plist);
//打印
void Show(List plist);
(2)list.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "list.h"
//初始化
void InitList(List plist) //List == Node *,plist即为头结点
{
assert(plist != NULL);
plist->next = NULL;
}
//头插法
bool Insert_head(List plist,int val)
{
Node *p = (Node *)malloc(sizeof(Node)); //p即为新节点
p->data = val; //p的data域设为val
p->next = plist->next; //将plist存储的下一个节点的地址赋值给p
plist->next = p; //将头结点的下一个节点设置为p
return true;
}
//尾插法
bool Insert_tail(List plist,int val)
{
//第一步,设置新节点
Node *p = (Node *)malloc(sizeof(Node));
assert(p != NULL);
if(p == NULL)
{
return false;
}
p->data = val;
//第二步,找尾节点
Node *q;
for(q = plist;q->next != NULL;q = q->next);
//将p插入到q的后面
p->next = q->next;
q->next = p;
return true;
}
//在pos下标插入数据val
bool Insert_pos(List plist,int pos,int val)
{
//判断输入的位置是否正确
if(pos < 0)
{
return false;
}
//找到pos位置的前一个节点
Node *q;
int i;
for(i = 0,q = plist;q->next != NULL && i < pos;q = q->next,i++);
Node *p = (Node *)malloc(sizeof(Node));
p->data = val;
p->next = q->next;
q->next = p;
return true;
}
//查找,找到返回节点地址,没有找到返回NULL
Node *Search(List plist,int key)
{
assert(plist != NULL);
for(Node *p = plist->next;p->next != NULL;p = p->next)
{
if(p->data == key)
{
return p;
}
}
return NULL;
}
//查找key的前驱节点
static Node *SearchPri(List plist,int key)
{
for(Node *p = plist;p != NULL;p = p->next)
{
if(p->next->data == key)
{
return p;
}
}
return NULL;
}
//删除第一个key对应的节点
bool Delete(List plist,int key)
{
Node *p = SearchPri(plist,key);
if(p == NULL)
{
return false;
}
Node *q = p->next; //q指向要删除的节点
p->next = q->next; //将q从链表中剔除
free(q); //释放内存
return true;
}
//删除第一个数据节点,并通过rtval获得删除的值
bool Delete_head(List plist,int *rtval)
{
if(plist->next == NULL)
{
return false;
}
Node *p = plist->next;
if(rtval == NULL)
{
*rtval = p->data;
}
plist->next = p->next;
free(p);
return true;
}
//删除最后一个数据节点,并通过rtval获得删除的值
bool Delete_tail(List plist,int *rtval)
{
assert(plist != NULL);
if(plist == NULL)
{
return false;
}
if(plist->next == NULL)
{
return false;
}
Node *p = plist;//p为要删除的节点
Node *q = p; //q保存p的上一节点
while(p->next!= NULL)
{
q = p;
p = p->next;
}
if(rtval != NULL)
{
*rtval = q->data;
}
free(p);
q->next = NULL;
return true;
}
//获取长度,统计数据节点的个数
int GetLength(List plist)
{
int count = 0;
for(Node *p = plist->next;p != NULL;p = p->next)
{
count++;
}
return count;
}
//判空
bool IsEmpty(List plist)
{
if(plist->next == NULL)
{
return true;
}
return false;
}
//销毁所有节点
void Destroy(List plist)
{
Node *p;
while(plist -> next != NULL)
{
p = plist->next;
plist->next = p->next;
free(p);
}
}
//打印
void Show(List plist)
{
if(IsEmpty(plist))
{
return;
}
for(Node *p = plist->next;p != NULL;p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
}
(3)main.cpp:
#include <stdio.h>
#include "list.h"
int main()
{
Node head;//CreateList();
InitList(&head);
//Node p;//Node *p
//InitList(&p);
for(int i=0;i<10;i++)
{
Insert_tail(&head,i);
//Insert_head(&head,i);
}
Show(&head);
Insert_pos(&head,0,-30);
Show(&head);
Insert_pos(&head,5,30);
Show(&head);
Insert_pos(&head,12,300);
Show(&head);
Insert_pos(&head,14,3000);
Show(&head);
Delete(&head,30);
Show(&head);
Delete(&head,-30);
Show(&head);
Delete(&head,300);
Show(&head);
int a;
int *rtval = &a;
Delete_tail(&head,rtval);
Show(&head);
Destroy(&head);
Destroy(&head);
Show(&head);
return 0;
}
(4)OOP的实现:
class Link
{
public:
Link()
{
phead=new Node;
}
~Link()
{
Node*pcur=phead;
while(pcur!=NULL)
{
phead=phead->pnext;
delete phead;
pcur=phead;
}
}
void inserthead(int val)
{
Node*pcur=new Node(val);
pcur->pnext=phead->pnext;
phead->pnext=pcur;
}
void inserttail(int val)
{
Node*pcur=phead;
while(pcur->pnext!=NULL)
{
pcur=pcur->pnext;
}
pcur->pnext=new Node(val);
}
void deleteNode(int val)
{
Node*pcur1=phead;
Node*pcur2=phead->pnext;
while(pcur2!=NULL)
{
if(pcur2->data==val)
{
pcur1->pnext=pcur2->pnext;
delete pcur2;
pcur2=pcur1->pnext;
}
else
{
pcur1=pcur2;
pcur2=pcur2->pnext;
}
}
}
void show()
{
Node*pcur=phead->next;
while(pcur!=NULL)
{
cout<<pcur->data<<" ";
pcur=pcur->pnext;
}
}
private:
class Node
{
public:
Node(int data):pdata(data),pnext(NULL){}
int pdata;
Node*pnext;
};
Node*phead;
};