@TOC数据结构之链表(c语言)
前记
因为是机械专业学生,不像计算机专业的同学经常博客,这是我第一次写博客,排版可能会有些混乱,还望大家见谅。
学习了三天的链表,做一次总结和分享。
使用的软件是visual studio 2019
基本概念
1、线性表(Linear List):是由n(n>=0)个数据元素(结点)a1,a2,…an组成的有限序列。该序列中的所有结点具有相同的数据结构。其中数据元素的个数n称为线性表的长度。
2、顺序表:把线性表的结点按逻辑顺序依次存放在一组地址连续的存储单元里。用这种方法存储的线性表简称为顺序表。
3、链表:用一组任意的存储单元存储线性表中的数据元素。用这种方法存储的线性表简称为线性链表。
单链表
LNode *creat_LinkList_head(void) {
/* 头插法创建单链表,链表的头结点head作为返回值 */
int data;
LNode* head, * p;
head = (LNode*)malloc(sizeof(LNode));
head->next = NULL; /* 创建链表的表头head */
while (1) {
puts("输入想要保存的数据(输入32767时推出输入步骤:");
scanf("%d", &data);
if (data == 32767) break;
p = (LNode*)malloc(sizeof(LNode));
p->data = data;
p->next = head->next; head->next = p;
/* 钩链,新创建的节点总作为第一个节点 */
}
return(head);
}
LNode *creat_LinkList_tail(void) {
/* 尾插入法创建单链表,链表的头结点head作为返回值*/
int data;
LNode* head, * p, * q;
head = p = (LNode*)malloc(sizeof(LNode));
p->next = NULL; /* 创建单链表表头结点head */
while (1) {
puts("输入链表中的数字(输入32767时结束):");
scanf("%d", &data);
if (data == 32767) break;
q = (LNode*)malloc(sizeof(LNode));
q->data = data; /* 数据域赋值 */
q->next = p->next; p->next = q; p = q;
/* 钩链,新创建的结点总是作为最后一个结点 */
}
return(head);
}
ElemType Get_Elem(LNode* L, int i) {
int j; LNode* p;
p = L->next; j = 1; /* 使p指向第一个结点 */
while (p!= NULL && j < i) {
p = p->next; j++; /*移动指针p,j计数 */
}
if (j != i) return(-32768);
else return(p->data);
/* p为NULL表示i太大;j>i表示i为0 */
}
LNode* Locate_Node(LNode* L, int key) {
/* 在以L为头结点的单链表中查找值为key的第一个结点 */
LNode* p = L->next;
while (p != NULL && p->data != key) p = p->next;
if (p->data == key) return p;
else{
printf("所要查找的结点不存在!!\n");
return(NULL);
}
}
void Insert_LNode(LNode* L, int i, ElemType e) {
/* 在以L为头结点的单链表的第i个位置上插入值为e的结点 */
int j = 0; LNode* p, *q;
p = L->next; j = 1;
while (p!=NULL && j <( i - 1)) {
p = p->next; j++; /* 使p指向第一个结点 */
}
printf("j=%d", j);
printf("i=%d", i);
if (j != (i - 1)) printf("i太大或i为0!!\n");
else {
q = (LNode*)malloc(sizeof(LNode));
q->data = e;
q->next = p->next; p->next = q;
}
}
void Delete_LinkList_Locate(LNode* L, int i) {
/* 删除以L为头结点的单链表中的第i个结点 */
int j = 0; LNode* p, * q;
p = L;
q = L->next; j = 1;
while (p->next != NULL && j < i) {
p = q; q = q->next; j++;
}
if (j != i) printf("i太大或i为0!!\n");
else {
p->next = q->next; free(q);
}
}
void Delete_LinkList_key(LNode* L, int key) {
LNode* p = L, * q = L->next;
while (q != NULL && q->data != key) {
p = q; q = q->next;
}
if (q->data == key) {
p->next = q->next; free(q);
}
else printf("所要删除的节点不存在!!\n");
}
void Delete_LinkList_Node(LNode* L, int key) {
/* 删除以L为头结点的单链表中值为key的所有结点*/
LNode* p = L, * q = L->next;
while (q != NULL) {
if (q->data == key) {
p->next = q->next; free(q); q = p->next;
}
else {
p = q; q = q->next;
}
}
}
void Delete_Node_value(LNode* L) {
/* 删除以L为头结点的单链表中所有值相同的节点 */
LNode* p = L->next, * q, * ptr;
while (p != NULL) {
{
q = p; ptr = p->next;
/* 检查结点p的所有后继结点ptr */
while (ptr != NULL) {
if (ptr->data == q->data) {
q->next = ptr->next; free(ptr);
ptr = q->next;
}
else {
q = ptr; ptr = ptr->next;
}
}
p = p->next;
}
}
}
LNode* Merge_LinkList(LNode* La, LNode* Lb) {
/* 合并以La,Lb为头结点的两个有序单链表 */
LNode* Lc, * pa, * pb, * pc, * ptr;
Lc = La; pc = La;
pa = La->next; pb = Lb->next;
while (pa != NULL && pb != NULL) {
if (pa->data < pb->data) {
pc->next = pa; pc = pa; pa = pa->next;
}
/* 将pa所指的结点合并,pa指向下一个结点 */
if (pa->data > pb->data) {
pc->next = pb; pc = pb; pb = pb->next;
/* 将pa所指的结点合并,pa指向下一个结点 */
}
if (pa->data == pb->data) {
pc->next = pa; pc = pa; pa = pa->next;
ptr = pb; pb = pb->next; free(ptr);
/* 将pa所指的结点合并,pb所指结点删除*/
}
if (pa != NULL) pc->next = pa;
else pc->next = pb; /* 将剩余的结点链上 */
free(Lb);
return(Lc);
}
}
void Printf_LinkList(LNode* L) {
LNode* p;
p = L->next;
while (p != NULL) {
printf("%d", p->data);
p = p->next;
}
}
双向循环链表
typedef struct Dulnode {
ElemType data;
struct Dulnode* prior, * next;
}DulNode;
DulNode* creat_DulLinkList_head(void) {
/* 头插法创建单链表,链表的头结点head作为返回值 */
int data;
DulNode* head, * p;
head = (DulNode*)malloc(sizeof(DulNode));
head->next = head;
head->prior = head; /* 创建链表的表头head */
while (1) {
puts("输入想要保存的数据(输入32767时推出输入步骤:");
scanf("%d", &data);
if (data == 32767) break;
p = (DulNode*)malloc(sizeof(DulNode));
p->data = data;
p->next = head->next; head->next->prior = p;
head->next = p; p->prior = head;
/* 钩链,新创建的节点总作为第一个节点 */
}
return(head);
}
void Printf_DulLinkList(DulNode* L) {
DulNode* p;
p = (DulNode*)malloc(sizeof(DulNode));
p = L;
while (p->next != L) {
p = p->next;
printf("%d ", p->data);
}
}
DulNode* creat_DulLinkList_tail(void) {
/* 尾插入法创建单链表,链表的头结点head作为返回值*/
int data;
DulNode* head, * p, * q;
head = p = (DulNode*)malloc(sizeof(DulNode));
p->next = p; p->prior = p; /* 创建循环链表表头结点head */
while (1) {
puts("输入链表中的数字(输入32767时结束):");
scanf("%d", &data);
if (data == 32767) break;
q = (DulNode*)malloc(sizeof(DulNode));
q->data = data; /* 数据域赋值 */
q->next = p->next; q->next->prior = p;
p->next = q; q->prior = p;
p = q;
/* 钩链,新创建的结点总是作为最后一个结点 */
}
return(head);
}
ElemType Get_DulElem(DulNode* L, int i) {
int j; DulNode* p;
p = L->next; j = 1; /* 使p指向第一个结点 */
while (p != L && j < i) {
p = p->next; j++; /*移动指针p,j计数 */
}
if (j != i) return(-32768);
else return(p->data);
/* p为NULL表示i太大;j>i表示i为0 */
}
DulNode* Locate_DulNode(DulNode* L, int key) {
/* 在以L为头结点的单链表中查找值为key的第一个结点 */
DulNode* p = L->next;
while (p != L && p->data != key) p = p->next;
if (p->data == key) return p;
else {
printf("所要查找的结点不存在!!\n");
return(NULL);
}
}
void Insert_DulLNode(DulNode* L, int i, ElemType e) {
/* 在以L为头结点的单链表的第i个位置上插入值为e的结点 */
int j = 0; DulNode* p, * q;
p = L->next; j = 1;
while (p != NULL && j < (i - 1)) {
p = p->next; j++; /* 使p指向第一个结点 */
}
if (j != (i - 1)) printf("i太大或i为0!!\n");
else {
q = (DulNode*)malloc(sizeof(DulNode));
q->data = e;
q->next = p->next; p->next->prior= q;
p->next = q; q->prior = p;
}
}
void Delete_DulLinkList_Locate(DulNode* L, int i) {
/* 删除以L为头结点的循环双向链表中的第i个结点 */
int j = 0; DulNode* p, * q;
p = L;
q = L->next; j = 1;
while (p->next != L && j < i) {
p = q; q = q->next; j++;
}
if (j != i) printf("i太大或i为0!!\n");
else {
p->next = q->next; q->next->prior = p; free(q);
}
}
void Delete_DulLinkList_key(DulNode* L, int key) {
DulNode* p = L, * q = L->next;
while (q != L && q->data != key) {
p = q; q = q->next;
}
if (q->data == key) {
p->next = q->next; q->next->prior = p; free(q);
}
else printf("所要删除的节点不存在!!\n");
}
void Delete_DulLinkList_Node(DulNode* L, int key) {
/* 删除以L为头结点的循环双向链表中值为key的所有结点*/
DulNode* p = L, * q = L->next;
while (q != L) {
if (q->data == key) {
p->next = q->next; q->next->prior = p; free(q); q = p->next;
}
else {
p = q; q = q->next;
}
}
}
void Delete_DulNode_value(DulNode* L) {
/* 删除以L为头结点的循环双向链表中所有值相同的节点 */
DulNode* p = L->next, * q, * ptr;
while (p != L) {
{
q = p; ptr = p->next;
/* 检查结点p的所有后继结点ptr */
while (ptr != L) {
if (ptr->data == q->data) {
q->next = ptr->next; q->next->prior = p; free(ptr);
ptr = q->next;
}
else {
q = ptr; ptr = ptr->next;
}
}
p = p->next;
}
}
}
DulNode* Merge_DulLinkList(DulNode* La, DulNode* Lb) {
/* 合并以La,Lb为头结点的两个有序单链表 */
DulNode* Lc, * pa, * pb, * pc, * ptr;
Lc = La; pc = La;
pa = La->next; pb = Lb->next;
while (pa != La && pb != Lb) {
if (pa->data < pb->data) {
pc->next = pa; pa->prior = pc; pc = pa; pa = pa->next;
}
/* 将pa所指的结点合并,pa指向下一个结点 */
if (pa->data > pb->data) {
pc->next = pb; pb->prior = pc; pc = pb; pb = pb->next;
/* 将pa所指的结点合并,pa指向下一个结点 */
}
if (pa->data == pb->data) {
pc->next = pa; pa->prior = pc; pc = pa; pa = pa->next;
ptr = pb; pb->prior->next = ptr->next; pb->next->prior = pb->prior; free(ptr);
/* 将pa所指的结点合并,pb所指结点删除*/
}
if (pa != La) {
pc->next = pa; pa->prior = pc;
}
else {
printf("hello");
pc->next = pb; /* 将剩余的结点链上 */
pb->prior = pc;
//Lb->prior->next = Lc; Lc->prior = Lb->prior;
while (pb ->next!= Lb) {
pb = pb -> next;
printf("此时pb->data=%d", pb->data);
}
pb->next = Lc; Lc->prior = pb;
free(Lb);
}
return(Lc);
}
} //该函数有问题,需改变
一元多项式的表示和相加
typedef struct ploy {
float coef; /*系数部分*/
int expn; /*指数部分*/
struct ploy* next;
}Ploy;
Ploy* creat_ploy(void) {
/* 尾插入法创建单链表,链表的头结点head作为返回值*/
float coef;
int expn;
Ploy* head,*p,*q;
head = p = (Ploy*)malloc(sizeof(Ploy));
p->next = NULL; /* 创建单链表表头head */
while (1) {
printf("输入系数和相应次数(输入32767 32767结束):");
scanf("%e %d", &coef, &expn);
//printf("coef=%e,expn=%d\n", coef, expn);
if (coef == 32767 && expn == 32767) break;
else {
q = (Ploy*)malloc(sizeof(Ploy));
q->coef = coef; q->expn = expn; /*数据域赋值*/
q->next = p->next; p->next = q; p = q;
/*钩链,新创建的结点总是最后一个结点*/
}
}
return(head);
}
Ploy* add_ploy_delete(Ploy* La, Ploy* Lb) {
Ploy* Lc, * pc, * pa, * pb, * ptr; float x;
Lc = pc = La;
pa = La->next; pb = Lb->next;
while (pa != NULL && pb!= NULL) {
if (pa->expn < pb->expn) {
pc->next = pa; pc = pa; pa = pa->next;
/* 将pa所指的结点合并,pa指向下一个结点 */
}
if (pa->expn > pb->expn) {
pc->next = pb; pc = pb; pb = pb->next;
/* 将pb所指的结点合并,pb指向下一个结点 */
}
else if (pa->expn = pb->expn) {
x = pa->coef + pb->coef;
if (abs(x) <= 1.0e-6) {
/* 如果系数和为0,删除两个节点 */
ptr = pa; pa = pa->next; free(ptr);
ptr = pb; pb = pb->next; free(ptr);
}
else {
pc->next = pa; pa->coef = x;
pc = pa; pa = pa->next;
ptr = pb; pb = pb->next; free(ptr);
}
}
} /* end of while*/
if (pa == NULL) pc->next = pb;
else pc->next = pa;
return(Lc);
}
void Printf_polyList(Ploy* L) {
Ploy* p;
p = L->next;
while (p != NULL) {
printf("%e %d\n", p->coef,p->expn);
p = p->next;
}
}
Ploy* add_ploy_reserve(Ploy* La, Ploy* Lb) {
/*将以La,Lb为头指针表示的一元多项式相加,生成一个新的结果多项式*/
Ploy* Lc,* pc, * pa, * pb, * p; float x;
Lc = pc = (Ploy*)malloc(sizeof(Ploy));
pa = La->next; pb = Lb->next;
while (pa != NULL && pb != NULL) {
if (pa->expn < pb->expn) {
p = (Ploy*)malloc(sizeof(Ploy));
p->coef = pa->coef; p->expn = pa->expn;
p->next = NULL;
/*生成一个新的结果结点并赋值*/
pc->next = p; pc = p; pa = pa->next;
}/* 生成的结点插入结果链表的最后,pa指向下一个结点 */
if (pa->expn > pb->expn) {
p = (Ploy*)malloc(sizeof(Ploy));
p->coef = pb->coef; p->expn = pb->expn;
p->next = NULL;
/* 生成一个新的结果结点并赋值 */
pc->next = p; pc = p; pb = pb->next;
}/* 生成的结点插入结果链表的最后,pb指向下一个结点 */
if (pa->expn == pb->expn) {
x = pa->coef + pb->coef;
if (abs(x) <= 1.0e-6) {
/* 系数和为0,pa,pb分别指向后继结点*/
pa = pa->next; pb = pb->next;
}
else {
/* 若系数和不为0,生成的结点插入到结果链表的最后,
pa,pb分别指向后继结点 */
p = (Ploy*)malloc(sizeof(Ploy));
p->coef = x; p->expn = pb->expn;
p->next = NULL;
/* 生成一个新的结果结点并赋值 */
pc->next = p; pc = p;
pa = pa->next; pb = pb->next;
}
}
}/* end of while */
if (pb != NULL) {
while (pb != NULL) {
p = (Ploy*)malloc(sizeof(Ploy));
p->coef = pb->coef; p->expn = pb->expn;
p->next = NULL;
/* 生成一个新的结果节点并赋值*/
pc->next = p; pc = p; pb = pb->next;
}
}
if (pa != NULL) {
while (pa != NULL) {
p = (Ploy*)malloc(sizeof(Ploy));
p->coef = pb->coef; p->expn = pb->expn;
p->next = NULL;
/* 生成一个新的结果节点并赋值*/
pc->next = p; pc = p; pa = pa->next;
}
}
return(Lc);
}
main函数及.h文件注意事项
其他不多说了,以link.h及其main.c为例
link.h—>
#ifndef LINK_H_INCLUDE
#define LINK_H_INCLUDE
typedef int ElemType;
struct Lnode;
typedef struct Lnode LNode;
LNode *creat_LinkList_head(void);
LNode *creat_LinkList_tail(void);
ElemType Get_Elem(LNode* L, int i);
LNode* Locate_Node(LNode* L, int key);
void Insert_LNode(LNode* L, int i, ElemType e);
void Delete_LinkList_locate(LNode* L, int i);
void Delete_LinkList_key(LNode* L, int key);
void Delete_LinkList_Node(LNode* L, int key);
void Delete_Node_value(LNode* L);
LNode* Merge_LinkList(LNode* La, LNode* Lb);
void Printf_LinkList(LNode* L);
#endif
main->
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include<malloc.h>
#include "dullink.h"
#include "link.h"
typedef struct Lnode {
ElemType data; /*数据域,保存结点的值*/
struct Lnode* next;/*指针域*/
}LNode; /*结点的类型*/
int main()
{
LNode* link1;
LNode* link2;
LNode* link3;
link1 = creat_LinkList_head();
Printf_LinkList(link1);
link2 = creat_LinkList_tail();
Printf_LinkList(link2);
link3= Merge_LinkList(link1,link2);
Printf_LinkList(link3);
}
希望可以坚持把数据结构学完。