单链表的操作
头结点:链表的第一个有效结点前面的结点,头结点并不存放有效数据,也就是数据域为空,加头结点的主要目的是为了方便链表的操作。
首节点:链表的第一个有效结点,结点包含数据域和指针域。
尾结点:尾结点的指针域为空。
头指针:指向头结点的指针变量,它存放了头结点的地址(在这里注意一下,指针变量存放的是地址,也就是说头指针存放的是头结点的地址,一般通过头指针对链表进行操作)。
具体实现如下:
#include<iostream>
using namespace std;
#define Status int
#define ElemType int
#define ERROR -1
#define OK 1
int i, j;
typedef struct LNode{ //结构体定义
ElemType data;
struct LNode *next;
}LNode, *LinkList;
LNode *p;
LNode *q;
void CreateList_L(LinkList &L, int n) //创建一个链表
{
cout << "输入链表的数据:";
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL; //创建头结点
int a[20];
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (i = n; i > 0; i--)
{
p = (LinkList)malloc(sizeof(LNode)); //头插法插入数据
p->data = a[i];
p->next = L->next;
L->next = p;
}
}
Status LisInsert_L(LinkList &L, int i, ElemType e)
{
LinkList s; //在链表的第i个元素之前插入新元素
p = L; j = 0;
while (p&&j < i - 1)
{
p = p->next;
++j;
}
if (!p || j>i - 1)
return ERROR;
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
Status ListDelete_L(LinkList &L, int i, ElemType &e)
{
p = L; j = 0;
while (p->next&&j < i - 1) //删除第i个元素
{
p = p->next; ++j;
}
if (!(p->next) || j>i - 1)
return ERROR;
q = p->next;
p->next = q->next;
e = q->data;
free(q);
return OK;
}
int GetLength(LinkList &L)
{
p = L->next; int length = 0; //获得链表的长度
while (p != NULL)
{
length++;
p = p->next;
}
return length;
}
ElemType GetData(LinkList &L, ElemType &e, int i)
{
p = L->next; //获得链表第i个元素的数据
j = 1;
while (p&&j < i)
{
p = p->next;
++j;
}
if (!p || j>i)
return ERROR;
e = p->data;
return e;
}
ElemType fixData(LinkList &L, ElemType &e, int i)
{
p = L->next; // 修改第i个元素
j = 1;
while (p&&j < i)
{
p = p->next;
++j;
}
if (!p || j>i)
return ERROR;
p->data = e;
return e;
}
void show(LinkList &L)
{
p = L->next;
cout << "链表所存数据为:";
while (p)
{
cout << p->data << ' ';
p = p->next;
}
cout << endl;
}
int main()
{
LinkList L;
int x = 0;
int n = 0;
cout << "请输入链表的元素个数:";
cin >> n;
CreateList_L(L, n);
show(L);
cout << "请输入插入数据的位置:";
cin >> n;
cout << "请输入插入数据:";
cin >> x;
LisInsert_L(L, n, x);
show(L);
cout << "链表的长度为:" << GetLength(L) << endl;
cout << "请输入元素序号,查询该元素数据:";
cin >> n;
cout << GetData(L, x, n) << endl;
cout << "请输入元素序号,修改该元素数据:";
cin >> n;
cout << "请输入修改的元素数据:";
cin >> x;
fixData(L, x, n);
show(L);
cout << "请输入元素序号,删除该元素:";
cin >> n;
ListDelete_L(L, n, x);
show(L);
return 0;
}
上面实现的主要是单链表,另外还有双链表、循环链表、非循环链表等其他几种常见链表。双链表的特殊性表现在每个基本结点有两个指针域;循环链表的特性主要表现在,在循环链表中,通过任何一个结点可以找到其他所有结点。