单链表结构体类型定义:
#include<stdio.h>
#include<malloc.h>
typedef struct LNode {
int data;
struct LNode* next;//next自引用,指向同类型
}LinkNode;
单链表的创建方法一:头插法(倒过来)
void CreateLNodeH1(LinkNode*& L, int a[], int n)
{//头插法1,顺序相反
L = (LinkNode*)malloc(sizeof(LinkNode));
L->next = NULL;//注意如果不置空则是野指针
int i = 0;
LinkNode* s;
for (i = 0; i < n; i++)
{
s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = a[i];
s->next = L->next;
L->next = s;
}
}
由于是,故得到的单链表元素索引与给定数组索引相反。
创建方法二:依然是头插法,但是在赋值时将数组最后一个元素赋值给第一个创建的节点(创建完后是最后一个),将数组倒数第二个元素赋值给第二个创建的节点(创建完后是倒数第二个节点),以此类推。
void CreateLNodeH2(LinkNode*& L, int a[], int n)
{//头插法2,反反的正,顺序相同
L = (LinkNode*)malloc(sizeof(LinkNode));
LinkNode* s; int i;
L->next = NULL;
for (i=0;i<n;i++)
{
s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = a[n-i-1];
s->next = L->next;
L->next = s;
}
}
创建方法三:尾插法,通过双指针依次往后处理。
void CreateLNodeR(LinkNode*& L, int a[], int n)
{//尾插法,两个指针依次前进
L = (LinkNode*)malloc(sizeof(LinkNode));
LinkNode* p, * q=L;
for (int i = 0; i < n; i++)
{
p = (LinkNode*)malloc(sizeof(LinkNode));
p->data = a[i];
q->next = p;
q=p;
}
q->next = NULL;
}
最后顺序与数组相同。
单链表的初始化:用malloc函数开辟头节点的空间,且指向空。
void InitLNode(LinkNode*& L)
{
L = (LinkNode*)malloc(sizeof(LinkNode));
//给头节点开辟内存
L->next = NULL;
}
单链表的销毁:从头节点开始依次往后释放各个节点的内存,剩最后一个节点时退出循环,再将其free();
void DestroyLNode(LinkNode*& L)
{
LinkNode* pre,* p;
pre = L; p = pre->next;
while (p!= NULL)
{
free(pre);
pre = p;
p = pre->next;
}
//从头节点到尾节点依次释放空间,还剩最后一个节点时循环结束
free(pre);//释放最后一个节点的内存
}
检查单链表是否为空:
bool LNodeEmpty(LinkNode* L)
{
return L->next == NULL;
}
//头节点的next是否为空
求单链表的长度:每循环一次count+1,直到p为最后一个节点,返回count。
int LNodeLength(LinkNode* L)
{
LinkNode* p = L;
int count = 0;
while (p ->next!= NULL)
{
p = p->next;
count++;
}
return count;
}
//while循环,p依次往后
依次输出单链表元素:
void DispLNode(LinkNode* L)
{
LinkNode* p = L->next;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//依次输出
根据单链表的索引取值:索引有效才为真,否则为假。
bool GetLNode(LinkNode* L, int i, int& e)
{
LinkNode* p = L;
int j = 0;
while (j < i && p != NULL)
{
j++;
p = p->next;
}
if (p == NULL)
return false;
else
{
e = p->data;
return true;
}
}
根据单链表的元素值求索引:当索引小于单链表长度且存在该元素才返回,否则返回-1。
int LocateLNode(LinkNode* L,int e)
{
LinkNode* s = L->next;
int count = 0;
while (s->data!=e && s != NULL)
{
s = s->next;
count++;
}
if (s == NULL)
return -1;
else
return count;
}
在单链表中插入元素:当索引有效才插入。
void InsertLNode(LinkNode*& L, int i, int e)
{
LinkNode* s = L,*r;
int j = 0;
while (j < i && s->next != NULL)
{
s = s->next;
j++;
}
if (s == NULL)
{
printf("索引不合法。\n");
}
else
{
r = (LinkNode*)malloc(sizeof(LinkNode));
r->data = e;
r->next = s->next;
s->next = r;
DispLNode(L);
}
}
插入元素时,先用malloc开辟一个节点空间,再进行赋值,然后通过
r->next = s->next;
s->next = r;
进行插入节点操作。
单链表的元素删除:同样,索引合法才能删除
void DeleteLNode(LinkNode*& L, int i, int& e)
{
int j = 0;
LinkNode* s=L,*r;
while (j<i && s != NULL)
{
j++;
s = s->next;
}
if (s == NULL)
printf("索引不合法。\n");
else
{
if(s->next==NULL)
printf("索引不合法。\n");
else
{
e = s->next->data;
r = s->next;
s->next = s->next->next;
free(r);
DispLNode(L);
}
}
}
在进行元素删除操作时,先将值赋出去,再
r = s->next;
s->next = s->next->next;
free(r);
如图:
最后,通过main()函数实现。
int main()
{
LinkNode* L;
int a[] = { 1,2,3,4,5,6,7 };
InitLNode(L);
CreateLNodeH2(L, a, 7);
DispLNode(L);
int e1 = 0;
if (GetLNode(L, 2, e1))
{
printf("%d\n", e1);
}
DispLNode(L);
bool bo = LNodeEmpty(L);
if (bo)
{
const char* a = "True";
printf("\"The list is empty\" is %s.\n", a);
}
else
{
const char* a = "False";
printf("\"The list is empty\" is %s.\n", a);
}
printf("The locate of 3 is %d.\n",LocateLNode(L,3));
InsertLNode(L,4,100);
int e = 0;
DeleteLNode(L, 8, e);
printf("%d\n", e);
DestroyLNode(L);
return 0;
}
其中部分对元素的查找,插入和删除中有些是逻辑位置,有些是物理位置。