这篇文章主要介绍了C语言实现单链表基本操作方法,文章围绕主题展开详细介绍,具有一定的参考价值,需要的小伙伴可以参考一下
存储结构
typedef int dataType;//爱护据类型
typedef struct Node {
DataType data; // 结点数据
struct Node *next; // 指向下一个结点的指针
} Node, *LinkList;
基本功能
- 头插法创建单链表void CreateListHead( LinkList &head)
- 尾插法创建单链表void CreateListTail( LinkList &head)
- 获取指定位置的元素 int GetElement(LinkList head, int i, DataType &e)
- 获取指定元素的位置 int LocateElement(LinkList head, int e)
- 在指定位置插入元素 int InsertList(LinkList head, int i, DataType e)
- 删除指定位置的元素 int DeleteList(LinkList head, int i, DataType &e)
- 获取单链表的长度 int LengthLinkList(LinkList head)
- 合并两个非递减的单链表 void MergeList(LinkList La, LinkList Lb, LinkList &Lc)
- 寂链表void Destroy( LinkList &L)
- 遍历打印单链表中的所有元素 void PrintList(LinkList head)
头插法创建单链表
每次添加链的结点都能找到头结点的第1号位置,所以创建单表中的元素的顺序是输入元素的逆序。
/**
* 头插法创建单链表,输入以-1结束
*/
void CreateListHead(LinkList &head) {
DataType x;
LinkList p;
head = (LinkList)malloc(LEN);
head->next = NULL;
scanf("%d", &x);
while (x != -1) {
p = (LinkList)malloc(LEN);
p->data = x;
p->next = head->next; // 新增的结点指向头结点的下一个结点
head->next = p; // 头结点指向新增的结点
scanf("%d", &x);
}
}
尾插法创建单链表
每次新增的结点都放在单链表的后面,接下来和接下来的顺序保持一致。
/**
* 尾插法创建单链表,输入以-1结束
*/
void CreateListTail(LinkList &head) {
LinkList p, q;
DataType x;
head = (LinkList)malloc(LEN);
q = head;
scanf("%d", &x);
while (x != -1) {
p = (LinkList)malloc(LEN);
p->data = x;
q->next = p;
q = p;
scanf("%d", &x);
}
q->next = NULL;
}
获取指定位置的元素
/**
* 获取指定位置的元素
* @param head 指向单链表头结点的指针(头指针)
* @param i 位置
* @param e 用来存放对应位置的元素值
* @return 0:获取失败;1:获取成功
*/
int GetElement(LinkList head, int i, DataType &e) {
LinkList p = head->next;
int j = 1;
while (p && j < i) { // 依次后移,直至为空或到达位置
p = p->next;
j++;
}
if (!p || j > i) { // p为空表示位置超过最大位置,j > i表示位置不合法(i < 1)
return 0;
}
e = p->data;
return 1;
}
在指定位置插入元素
/**
* 在单链表插入元素到位置i
* @param head 单链表的头指针
* @param i 插入位置
* @param e 插入元素
* @return 1:插入成功,0:插入失败
*/
int InsertList(LinkList head, int i, DataType e) {
LinkList p = head; // 从头结点开始
int j = 1;
while (p && j < i) { // 找到插入位置的前一个结点
p = p->next;
j++;
}
if (!p || j > i) { // p为空或i < 1,插入位置不合法
return 0;
}
LinkList q = (LinkList)malloc(LEN); // 创建新结点
q->data = e;
q->next = p->next; // 将新结点指向前一个结点的后一个结点
p->next = q; // 前一个结点指向新结点
// 执行上述两个操作后,达到的效果是新结点插入到了前一个结点的后面
}
删除指定位置的元素
/**
* 删除指定位置的元素
* @param head
* @param i 位置
* @param e 被删除的元素的值存放在e中
* @return 1:删除成功,0:删除失败
*/
int DeleteList(LinkList head, int i, DataType &e) {
LinkList p = head;
int j = 1;
while (p && j < i) { // 找到位置的前一个结点
p = p->next;
j++;
}
if (!p || j > i) {
return 0;
}
LinkList s = p->next;
e = s->data;
p->next = s->next; // 改变前一个结点的指向,使其指向删除结点的后一个结点
free(s);
return 1;
}
获取单链表的长度
/**
* 获取单链表的长度
* @param head
* @return 单链表的长度
*/
int LengthLinkList(LinkList head) {
LinkList p = head->next;
int count = 0;
while (p) {
count++;
p = p->next;
}
return count;
}
合并两个非递减的单链表
合并两个非递减的单链,新链表仍然保持非递减。
/**
* 合并两个非递减的单链表,新的链表仍然非递减
* @param La
* @param Lb
* @param Lc
*/
void MergeList(LinkList La, LinkList Lb, LinkList &Lc) {
LinkList pa, pb, pc;
pa = La->next;
pb = Lb->next;
pc = Lc = (LinkList)malloc(LEN);
while (pa && pb) {
if (pa->data <= pb->data) {
pc->next = pa;
pc = pa;
pa = pa->next;
} else {
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
pc->next = pa ? pa : pb;
free(Lb);
}
晴链表
/**
* 销毁链表
*/
void Destroy(LinkList &L) {
LinkList p, q;
p = L;
while (p) { // 遍历所有结点,释放内存
q = p;
p = p->next;
free(q);
}
L = NULL; // L置为NULL
}
遍历打印单链表
/**
* 遍历打印单链表的所有元素
*/
void PrintList(LinkList head) {
LinkList p = head->next;
if (p == NULL) {
cout << "List is NULL!" <<endl;
} else {
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
}
附上完整代码
#include<cstdlib>
using namespace std;
#define LEN sizeof(Node)
typedef int DataType;
typedef struct Node {
DataType data;
struct Node *next;
} Node, *LinkList;
/**
* 头插法创建单链表
* @param head
*/
void CreateListHead(LinkList &head) {
DataType x;
LinkList p;
head = (LinkList)malloc(LEN);
head->next = NULL;
scanf("%d", &x);
while (x != -1) {
p = (LinkList)malloc(LEN);
p->data = x;
p->next = head->next;
head->next = p;
scanf("%d", &x);
}
}
/**
* 尾插法创建单链表
* @param head
*/
void CreateListTail(LinkList &head) {
LinkList p, q;
DataType x;
head = (LinkList)malloc(LEN);
q = head;
scanf("%d", &x);
while (x != -1) {
p = (LinkList)malloc(LEN);
p->data = x;
q->next = p;
q = p;
scanf("%d", &x);
}
q->next = NULL;
}
/**
* 获取指定位置的元素
* @param head 单链表头指针
* @param i 位置
* @param e 获取的元素赋值该参数
* @return 0:获取失败;1:获取成功
*/
int GetElement(LinkList head, int i, DataType &e) {
LinkList p = head->next;
int j = 1;
while (p && j < i) {
p = p->next;
j++;
}
if (!p || j > i) {
return 0;
}
e = p->data;
return 1;
}
/**
* 获取某个元素的位置
* @param head
* @param e
* @return 元素的位置
*/
int LocateElement(LinkList head, int e) {
LinkList p = head->next;
int j = 1;
while (p && p->data != e) {
p = p->next;
j++;
}
if (!p) {
return 0;
}
return j;
}
/**
* 在单链表插入元素到位置i
* @param head 单链表的头指针
* @param i 插入位置
* @param e 插入元素
* @return 1:插入成功,0:插入失败
*/
int InsertList(LinkList head, int i, DataType e) {
LinkList p = head;
int j = 1;
while (p && j < i) {
p = p->next;
j++;
}
if (!p || j > i) {
return 0;
}
LinkList q = (LinkList)malloc(LEN);
q->data = e;
q->next = p->next;
p->next = q;
}
/**
* 删除指定位置的元素
* @param head
* @param i 位置
* @param e 被删除的元素的值存放在e中
* @return 1:删除成功,0:删除失败
*/
int DeleteList(LinkList head, int i, DataType &e) {
LinkList p = head;
int j = 1;
while (p && j < i) {
p = p->next;
j++;
}
if (!p || j > i) {
return 0;
}
LinkList s = p->next;
e = s->data;
p->next = s->next;
free(s);
return 1;
}
/**
* 获取单链表的长度
* @param head
* @return
*/
int LengthLinkList(LinkList head) {
LinkList p = head->next;
int count = 0;
while (p) {
count++;
p = p->next;
}
return count;
}
/**
* 合并两个非递减的单链表,新的链表仍然非递减
* @param La
* @param Lb
* @param Lc
*/
void MergeList(LinkList La, LinkList Lb, LinkList &Lc) {
LinkList pa, pb, pc;
pa = La->next;
pb = Lb->next;
pc = Lc = (LinkList)malloc(LEN);
while (pa && pb) {
if (pa->data <= pb->data) {
pc->next = pa;
pc = pa;
pa = pa->next;
} else {
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
pc->next = pa ? pa : pb;
free(Lb);
}
/**
* 销毁链表
* @param L
*/
void Destroy(LinkList &L) {
LinkList p, q;
p = L;
while (p) {
q = p;
p = p->next;
free(q);
}
L = NULL;
}
/**
* 遍历打印单链表的所有元素
* @param head
*/
void PrintList(LinkList head) {
LinkList p = head->next;
if (p == NULL) {
cout << "List is NULL!" <<endl;
} else {
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
}
int main() {
LinkList L;
printf("头插法创建单链表:(输入以-1结束)\n");
CreateListHead(L);
PrintList(L);
printf("尾插法创建单链表:(输入以-1结束)\n");
CreateListTail(L);
PrintList(L);
InsertList(L, 1, 100);
printf("在1号位置插入100后,单链表如下:\n");
PrintList(L);
DataType e;
DeleteList(L, 1, e);
printf("删除1号位置的元素,被删除的元素为:\n");
printf("删除后的单链表为:\n");
PrintList(L);
printf("单链表的长度为:%d\n", LengthLinkList(L));
GetElement(L, 1, e);
printf("1号位置的元素为:%d\n");
printf("元素4在单链表中的位置为:%d\n", LocateElement(L, 4));
cout << endl;
LinkList La, Lb, Lc;
printf("尾插法创建单链表La:\n");
CreateListTail(La);
PrintList(La);
printf("尾插法创建单链表Lb:\n");
CreateListTail(Lb);
PrintList(Lb);
MergeList(La, Lb, Lc);
printf("合并单链表La和Lb后的新单链表Lc如下:\n");
PrintList(Lc);
return 0;
}
运行结果:
注意:
写法采用了C++引用参数的写法,LinkList &head,C语言下不支持这种写法,需要在C++环境下使用,即.cpp文件。
下面附上C语言的:
/**
* LinkList 本身已经是结构体指针,参数再使用LinkList *的形式
* 可以理解为要想改变一个结构体指针,则需要取指针的指针。
* 类似于改变int a,则需要使用 int *a,这里要改变LinkList head,则需要使用LinkList *head
*/
void CreatListTail(LinkList *head) {
int x;
LinkList *p, *q;
*head = (LinkList *) malloc(LEN);
q = *head;
scanf("%d", &x);
while (x != -1) {
p = (LinkList *) malloc(LEN);
p->data = x;
q->next = p;
q = p;
scanf("%d", &x);
}
q->next = NULL;
}
// 可以不传参,函数里面定义头指针,创建链表,然后把头指针返回,主函数用结构体指针接收即可
LinkList CreateListhead() {
int x;
LinkList *head, *p;
head = (LinkList *) malloc(LEN);
head->next = NULL;
scanf("%d", &x);
while (x != -1) {
p = (LinkList *) malloc(LEN);
p->data = x;
p->next = head->next;
head->next = p;
}
return head;
}
到此这篇关于C语言实现单链表基本操作方法的文章就介绍到这了,更多相关C语言单链表内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!
沃梦达教程
本文标题为:C语言实现单链表基本操作方法


猜你喜欢
- C语言qsort()函数的使用方法详解 2023-04-26
- C语言手把手带你掌握带头双向循环链表 2023-04-03
- C语言详解float类型在内存中的存储方式 2023-03-27
- Qt计时器使用方法详解 2023-05-30
- c++ const 成员函数,返回一个 const 指针.但是返回的指针是什么类型的 const? 2022-10-11
- C++ 数据结构超详细讲解顺序表 2023-03-25
- 详解C语言中sizeof如何在自定义函数中正常工作 2023-04-09
- ubuntu下C/C++获取剩余内存 2023-09-18
- 我应该为我的项目使用相对包含路径,还是将包含目录放在包含路径上? 2022-10-30
- Easyx实现扫雷游戏 2023-02-06