链表的好处在于插入和删除元素时只需改变指针的指向,减少操作次数。链表的存储结构可以是顺序的(静态链表)也可以是无序的。缺点是随机访问时需要遍历整个表。本文用无序的存储结构实现了单链表。
//线性表的链式表示(单向链表)
//lovesunmoonlight
//2017.3.29
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<fstream>
using namespace std;
ofstream out;
typedef struct ElemType
{
int key; //键值
double data; //数据域
};
typedef struct LNode
{
ElemType data; //数据域
LNode* next; //指针域
}LNode,*LinkList;
bool GetElem_L(const LinkList& L,int i,ElemType& e)
{
LNode* p=L->next; //初始化p为第一个结点
int j=1;
while(p&&j<i)
{
p=p->next;
++j;
}
e=p->data;
return true;
}
//在第i个位置插入,核心是修改第i-1个位置节点的指针域
bool ListInsert_L(LinkList& L,int i,ElemType e)
{
LNode* p=L;
int j=0;
//寻找第i-1个节点
while(p&&j<i-1)
{
p=p->next;
++j;
}
if(!p||j>i-1)
return false;
LNode* s=(LinkList)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
bool ListDelete_L(LinkList& L,int i,ElemType& e)
{
LNode* p=L;
int j=0;
//寻找第i-1个节点
while(p&&j<i-1)
{
p=p->next;
++j;
}
if(!p||j>i-1)
return false;
LNode* q=p->next;
e=q->data;
p->next=q->next; //修改i-1位置的指针,指向被删除节点的下一个位置
free(q); //释放节点空间
return true;
}
//输入数据
void input(LNode* &p)
{
p->data.key=rand()%50;
p->data.data=rand()%100;
}
//生成长度为n的链表(逆序)
void CreateList_L(LinkList& L,int n)
{
L=(LinkList)malloc(sizeof(LNode));
L->next=NULL; //带头结点
for(int i=n;i>0;--i)
{
LNode* p=(LinkList)malloc(sizeof(LNode)); //生成新节点
input(p); //输入数据
p->next=L->next; //即NULL
L->next=p; //插入到表头
}
}
//输出
void output(const LinkList& L)
{
LNode* p=L->next; //初始化p为第一个结点
out<<"Key Data"<<endl;
while(p)
{
out<<p->data.key<<" "<<p->data.data<<endl;
p=p->next;
}
}
//判断链表是否为空
bool IsEmpty_L(const LinkList& L)
{
if(L->next==NULL)
return true;
return true;
}
int main()
{
out.open("result.txt");
//初始化表
LinkList L;
CreateList_L(L,10);
out<<"Initialized: "<<endl;
output(L);
ElemType temp;
temp.key=11111;
temp.data=3.1415;
ListInsert_L(L,6,temp);
out<<"After ListInsert_L: "<<endl;
output(L);
ListDelete_L(L,4,temp);
out<<"After ListDelete_L: "<<endl;
output(L);
out<<"The element has been deleted: ";
out<<temp.key<<" "<<temp.data<<endl;
return 0;
}