本人使用VC2019进行编程,该软件C中可以使用C++语法,故可能不严谨
前言
在校大学生,学习差,写写帖子长长写代码的记性。不好的地方大家请指正,谢谢。
一、链表
以我自己的理解说一下链表是什么东西,不按照书上那样官方的解释。链,看到这个字我想到的是链条。比如自行车,摩托车就是依靠链条传动的,那个链条呢是一节扣一节的。顺着这一节可以找到下一节。那么数据结构中的链条其实也是这样的,一个节点扣紧一个节点。
1.逻辑结构
链表的逻辑结构也是线性的。
2.内存中的存储形式
画个图讲讲
大概阐述一下上图的意思。可以看到ABCD在计算机内存中并不是都连续存在的。我们在定义顺序表的时候是不是要求了存储的数据是在一片连续的空间中?但是在链表中就没有这样的要求,所以基于两种不同的存储方式,使得链表顺序表拥有不同的优缺点。A是怎么到B,B又怎么到的C,C到D的。这就是指针了。另外我觉的也不要再把指针又替换概念为地址。我觉得指针两个字就很形象,就是生活中那种指针,指到哪就是哪,那么A的指针就是指向B,BCD同理。
二、代码实现
1.链表的数据结构代码
typedef struct list {
int data;
struct list* next;
}lnode,*linklist;
/*
在这儿我得说说lnode,*linklist在这里的意思
lnode,*linklist大家都明白是这个结构体的名字。
但是大家有没有发现这个结构体的定义好像存一个数据?因为严格来说我们定义的是链表的一个节点。
我们只需要用很多个节点让他们的指针指起来就是一整个表了。
另外编程中有些大家都遵守的规则,lnode就是用来特指一个节点的。而*linklist是用来表示一整个链表,
但是你得明白,*linklist也只是指向了一个节点,只不过是链表的第一个节点而已。
*/
2.高级一点点的链表
typedef struct student {
int id;
char name[20];
}stu;
typedef struct list {
stu data;
struct list* next;
}lnode,*linklist;
/*在学数据结构那就别整天顺序表,链表里套语言自带数据类型(int char ...)了
自己用结构体套用起来,这里面用到char数组的时候会有一些细节容易出错
细心点
*/
3.完整代码
#include<stdio.h>
#include <corecrt_malloc.h>
#include <string.h>
typedef struct student {
int id;
char name[20];
}stu;
typedef struct list {
stu data;
struct list* next;
}lnode,*linklist;
void createlist(linklist &l,int len) { //头插法创建链表,会导致链表中元素为输入时的倒序
lnode *node;
for (int i = 0; i < len; i++)
{
stu s = {};
printf("input stuid:");
scanf("%d", &s.id);
printf("input stuname:");
scanf("%s", &s.name);
node =(lnode*) malloc(sizeof(lnode));
node->data = s;
node->next = l->next;
l->next = node;
printf("an data is create.\n");
}
}
void showlist(linklist l) {
lnode *p = l->next;
if (p != NULL) {
while (p)
{
printf("imformationis:%d %s\n", p->data.id, p->data.name);
p = p->next;
}
}
else
{
printf("Linklist is null.\n");
}
}
void findstu(linklist l,int iD) {
lnode* p = l->next;
while (p)
{
if (p->data.id == iD)
{
printf("find the student,information:%d %s\n", p->data.id, p->data.name);
break;
}
else
{
p = p->next;
}
}
if (p == NULL) {
printf("no exist this student.\n");
}
}
void findstu(linklist l, char namE[]) {
lnode* p = l->next;
while (p)
{
if (!strcmp(p->data.name,namE))
{
printf("find the student,information:%d %s\n", p->data.id, p->data.name);
break;
}
else
{
p = p->next;
}
}
if (p == NULL) {
printf("no exist this student.\n");
}
}
void insert(linklist &l,stu s,int iD) {
lnode* n = (lnode *)malloc(sizeof(lnode));
n->data = s;
lnode* p = l;
while (p&&p->data.id!=iD)
{
p = p->next;
}
if (p != NULL) {
n->next = p->next;
p->next = n;
printf("insert finish.\n");
}
else
{
printf("error.\n");
}
}
void alterstu(linklist& l) {
int iD;
printf("alter student id is:");
scanf("%d", &iD);
lnode* p = l->next;
while (p)
{
if (p->data.id == iD)
{
printf("find the student,information:%d %s\n", p->data.id, p->data.name);
stu s = {};
printf("input id for alter:");
scanf("%d", &s.id);
printf("input name for alter:");
scanf("%s", &s.name);
p->data = s;
printf("alter finished.\n");
break;
}
else
{
p = p->next;
}
}
if (p == NULL) {
printf("no exist this student.\n");
}
}
void Alterstu(linklist& l) {
char namE[20] = {};
printf("alter student name is:");
scanf("%s", &namE);
lnode* p = l->next;
while (p)
{
if (!strcmp(p->data.name,namE))
{
printf("find the student,information:%d %s\n", p->data.id, p->data.name);
stu s = {};
printf("input id for alter:");
scanf("%d", &s.id);
printf("input name for alter:");
scanf("%s", &s.name);
p->data = s;
printf("alter finished.\n");
break;
}
else
{
p = p->next;
}
}
if (p == NULL) {
printf("no exist this student.\n");
}
}
void deletestu(linklist& l,int iD) {
lnode* p = l;
while (p)
{
if (p->next->data.id==iD)
{
lnode* n = p->next;
p->next = n->next;
free(n);
printf("delete finished,\n");
break;
}
else
{
p = p->next;
}
}
}
void deletestu(linklist& l, char namE[]) {
lnode* p = l;
while (p)
{
printf("%s\n", namE);
if (!strcmp(p->next->data.name,namE))
{
lnode* n = p->next;
p->next = n->next;
free(n);
printf("delete finished,\n");
break;
}
else
{
p = p->next;
}
}
}
void meum() {
printf("------1.创建链表 2.显示链表元素------\n");
printf("------3.查找数据(id) 4.查找数据(name)----\n");
printf("------5.增加数据(loc) 6.增加数据(data)----\n");
printf("------7.修改数据(id) 8.修改数据(name)----\n");
printf("------9.删除数据(id) 10.删除数据(name)----\n");
}
int main() {
linklist l;
l = (linklist)malloc(sizeof(lnode));
l->next = NULL;
int key = 1,choose,temp;
char name[20] = {};
stu s = {};
while (key)
{
meum();
scanf("%d",&choose);
switch (choose)
{
case 1:
printf("input list length:");
scanf("%d",&temp);
createlist(l,temp);
break;
case 2:
showlist(l);
break;
case 3:
printf("input stuid for search:");
scanf("%d", &temp);
findstu(l, temp);
break;
case 4:
printf("input student name:");
scanf("%s", &name);
findstu(l, name);
break;
case 5:
printf("input id for insert:");
scanf("%d", &s.id);
printf("input name for insert:");
scanf("%s", &s.name);
printf("input id and insert after this id:");
scanf("%d", &temp);
insert(l,s,temp);
break;
case 6:
break;
case 7:
alterstu(l);
break;
case 8:
Alterstu(l);
break;
case 9:
printf("input stuid for delete:");
scanf("%d", &temp);
deletestu(l, temp);
break;
case 10:
printf("input stuname for delete:");
scanf("%s", &name);
deletestu(l, name);
break;
default:
printf("input the right data.\n");
break;
}
}
return 0;
}
总结
上面代码是用头插法创建的带头节点链表。还有不带头的,但是一般我们带头节点的用的多一点。链表还有尾插法创建,双向链表,循环链表等,但是不管怎么变,只需要能理解链表的本质,用指针指来指去就可以实现这些链表。后面我都会编程发布。