什么是线性表?

线性表就是一组数据的集合以某种特定方式排列。该排列方式中除第一个元素和最后一个元素外,每一个元素的前面和后面都有其他元素。第一个元素前面没有其他元素,最后一个元素后面没有其他元素。

线性表在计算机中有不同的存储方式,昨天我写的实现方式是顺序存储也就是说数据前后的数据在计算机的存储器中是一个一个挨着存的。今天的实现是单链表形式,数据在计算机中的存放位置仅仅是在逻辑上前后挨着,在计算机的存储器里并没有放在一起,数据之间通过指针实现逻辑上的互联。

一个线性表的单链表存储形式的存储形式如图:

单链表.png (9.83 KB, 下载次数: 0)

单链表

2020-11-29 11:17 上传

该图中,head指向的为单链表的头结点,该单链表中有两个数据(数据没有在图上写出来,鼠标写字太难了{:301_971:} )。

从图中可以看出:

链表中的每个节点包含一个数据和一个指针(指向下一个节点)。

链表有一个头节点,不存储元素内容,头节点的指向存储第一个元素的结点。

线性表为空时,头节点指针项为空(用0表示)。

线性表不为空时,链表中存储最后一个元素的指针项为空,表示后面没有元素了。

线性表元素从1开始标号。存储结构中,可以将头结点的编号视为0,实现逻辑编号与物理编号的统一。

head指针指向头结点。

单链表实现:list.h

typedef char EleType;

typedef struct node{

EleType data;

struct node * next;

} ChainNode;

typedef struct{

ChainNode * head;

} List;

List * CreateList(void);

void DestroyList(List *);

void ClearList(List *);

int ListInsert(List *,int,EleType);

int ListDelete(List *,int);

int ListAppend(List *,EleType);

int TraverseList(List *,int (*)(EleType *));

int GetElement(List * l,int n,EleType * data);

ChainNode* NewChainNode(EleType);

ChainNode* GetAddr(List *,int );

List* CreateList(void){

List * l = 0;

ChainNode * p = 0;

EleType * data = 0;

l = (List *)malloc(sizeof(List));

if(l == 0) return 0;

p = NewChainNode(*data);

if(p==0) return 0;

l->head = p;

return l;

}

void DestroyList(List * l){

ClearList(l);

free(l->head);

}

void ClearList(List * l){

while(l->head->next){

ListDelete(l,1);

}

}

int ListInsert(List * l,int n,EleType data){

ChainNode * p = 0;

ChainNode * newp = 0;

p = GetAddr(l,n-1);

if( p == 0 ) return 0;

newp = NewChainNode(data);

if(newp == 0 ) return 0;

newp->next = p->next;

p->next = newp;

return 1;

}

int ListDelete(List * l,int n){

ChainNode * p = 0;

ChainNode * temp = 0;

p = GetAddr(l,n-1);

if(p==0) return 0;

temp = p->next;

if(temp==0) return 0;

p->next = temp->next;

return 1;

}

int ListAppend(List * l,EleType data){

ChainNode * p = 0;

ChainNode * newp = 0;

p = l->head;

while(p->next)

p = p->next;

newp = NewChainNode(data);

if(newp == 0 ) return 0;

p->next = newp;

return 1;

}

int TraverseList(List * l, int (*f)(EleType  *data)){

ChainNode * p = 0;

int cnt = 0;

EleType * temp =0;

p = l->head->next;

while(p){

cnt++;

temp = &(p->data);

if(f(temp) == 0) return cnt;

p = p->next;

}

return -1;

}

int GetElement(List * l,int n,EleType * data){

ChainNode * p = 0;

if(n < 1) return 0;

p = GetAddr(l,n);

if(p == 0) return 0;

(*data)=p->data;

return 1;

}

ChainNode * NewChainNode(EleType data){

ChainNode * p = 0;

p = (ChainNode *)malloc(sizeof(ChainNode));

if(p == 0) return 0;

p->data = data;

p->next = 0;

return p;

}

ChainNode * GetAddr(List * l,int pos){

ChainNode * p = 0;

int cnt = 0;

p = l->head;

if(pos < 0) return 0;

while(p && cnt++ < pos){

p = p->next;

}

if(cnt < pos) return 0;

return p;

}

对list.h进行测试(检验程序的鲁棒性):m.c

#include"list.h"

#define RIGHT 0

#define WRONG 1

#define CREATELIST 0

#define LISTAPPEND 1

#define LISTINSERT 2

#define LISTDELETE 3

#define GETELEMENT 4

#define CLEARLIST  5

#define titleTest printf("your:");

#define titleSystem printf("\nsyst:");

int putE(EleType*);

void showResult(List*, int no, char *answer);

char* strArr[] =

{

"---------CreateList Test---------",

"---------ListAppend Test---------",

"---------ListInsert Test---------",

"---------ListDelete Test---------",

"---------GetElement Test---------",

"---------ClearList Test---------",

};

main()

{

char* arr = "assembly";

int n = 0;

List* list;

char chArr[10] = {0,0,0,0,0,0,0,0,0,0};

char ch;

list = CreateList();

puts(strArr[CREATELIST]);

if(!list) { puts("createList wrong!"); return; }

else      { puts("createList no nullpointer!");}

puts(""); getch();

for(n=0; arr[n]; n++) ListAppend(list, arr[n]);

showResult(list, LISTAPPEND, "assembly");

ListInsert(list,1,'

ListInsert(list,10,'>');

ListInsert(list,7,'-');

n = ListInsert(list,0,'0');

n = n + ListInsert(list,13,'0');

n = n + ListInsert(list,-1,'0');

showResult(list, LISTINSERT, "");

if(n) puts("insert error!");

n = 0;

ListDelete(list,1);

ListDelete(list,10);

ListDelete(list,6);

ListDelete(list,8);

ListDelete(list,1);

ListDelete(list,5);

n = ListDelete(list,0);

n = n + ListDelete(list, 6);

n = n + ListDelete(list, -1);

showResult(list, LISTDELETE, "sseml");

if(n) puts("list delete error!");

n = 0;

GetElement(list, 5, &ch); chArr[0] = ch;

GetElement(list, 1, &ch); chArr[1] = ch;

GetElement(list, 3, &ch); chArr[2] = ch;

n = GetElement(list, 6, &ch);

puts(strArr[GETELEMENT]);

titleTest printf("%s",chArr);

titleSystem puts("lse");

if(n) puts("getelement error!");

puts(""); getch();

ClearList(list);

showResult(list, CLEARLIST, "");

}

void showResult(List* list, int no, char *answer)

{

puts(strArr[no]);

titleTest TraverseList(list,putE);

titleSystem puts(answer);

puts(""); getch();

}

int putE(EleType* e)

{

printf("%c", *e);

return 1;

}

c语言头结点存放元素,【笔记】带头节点的单链表的C语言实现相关推荐

  1. 数据结构-带头节点的单链表(C语言)超详细讲解

    前面我们学到线性表的顺序存储结构(顺序表),发现它有着明显的缺点:插入和删除元素时需要频繁的移动元素,运算效率低.必须按事先估计的最大元素个数申请连续的存储空间.存储空间估计大了,造成浪费空间:估计小 ...

  2. 【数据结构】8. 队列(带头节点的单链表实现)(完整代码实现:初始化、入队列、出队列、获取队头元素、获取队尾元素、获取队列中有效元素的个数、判空、销毁)

    目录 Queue.h Queue.c test.c Queue.h #pragma once //采用带头节点的单链表实现队列typedef int DataType;typedef struct Q ...

  3. java带头节点的单链表_自己实现集合框架(五):带头结点单链表的实现

    这是系列文章,每篇文章末尾均附有源代码地址.目的是通过模拟集合框架的简单实现,从而对常用的数据结构和java集合有个大概的了解.当然实现没有java集合的实现那么复杂,功能也没有那么强大,但是可以通过 ...

  4. 【不带头节点的单链表】

    不带头节点的单链表 前言 一.结构体设计 二.函数实现 1. 初始化 2. 购买一个新节点 3. 头插 4. 尾插 5. 按位置插入 6. 头删 7. 尾删 8. 按位置删 总结 补充代码 前言 单链 ...

  5. 数据结构不带头节点跟带头节点的单链表区别,C语言代码展示

    单链表头插法 不带头结点 void FronttList1(List *L) {List p;ElemType x;printf_s("请输入一组数据,以'0'为结束符\n");s ...

  6. 不带头节点的单链表如何头插(多图易懂)

    文章目录 缘起 带头节点的头插 不带头节点的头插 错误的代码 为什么错误 如何修改 返回新的头指针 二级指针 缘起 本文想说的是单向非循环链表的头插.单向非循环链表,可以是带头节点的,也可以是不带头节 ...

  7. C语言将结点s赋给表L,数据结构-单链表

    一.单链表基本定义 线性表的链式存储:线性表采用链式方式将结点链接起来的存储结构称之链表.单链表结构,分前后两个域,date数据域:存放结点的值,next指针域:存放数据元素后继的位置.附设头结点的目 ...

  8. 借助栈将一个带头节点的单链表倒置

    分析: 先理解倒置: 倒置前:1->2->3 倒置后:3->2->1 思路:先沿着链表从头到尾扫一遍 将链表的每个结点的data的值依次入栈;  在沿着链表扫一遍 将栈中的元素 ...

  9. 头插法和尾插法建立带头节点的单链表

    有两种方法建立单链表,尾插法和头插法,他们的区别是:头插法是按照输入元素倒序建立,为尾插法为顺序插入,并且多一个尾节点,我们一般使用尾插法. 一.头插法 代码为: pCurr -> next = ...

  10. 带头节点的单链表逆置

    #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next ...

最新文章

  1. 怎么在Caffe中配置每一个层的结构
  2. bzoj 5090 组题
  3. python传递参数格式_Python语言学习基础篇之Python发送Post请求之根据参数位置传参、数据类型、不同方式传参...
  4. 【洛谷】【二分答案+最短路】P1462 通往奥格瑞玛的道路
  5. ubuntu man手册完善
  6. 全排列变种:限定 排列的差值范围 及 排列中的元素个数
  7. python+OpenCV图像处理(三)绘制简单的几何图形、显示文字
  8. docker Gitlab14.5.0 安装、配置、部署、使用
  9. css中hover的妙用!!
  10. 【算法】第76题 Minimum Window Substring
  11. 学习mongo系列(五) AND,$or,$type
  12. XML 数据挖掘 之 挖掘 XML 关联规则
  13. input失去焦点和获得焦点jquery焦点事件
  14. [Bug]Superset通过pyhive连接Spark SQL表名获取失败
  15. android wear5.0,Android Wear安卓5.0正式到来
  16. PAM-PDMDAAC聚丙烯酰胺-聚二甲基二烯丙基氯化铵/PEI-P(Asp-Hyd-ADR 聚乙烯亚胺-聚天冬氨酸
  17. AVR32单片机 矩阵按键 按键键值函数解析
  18. Raspberry pi 通过iphone手机访问
  19. Java岗大厂面试百日冲刺【Day54】— Redis4 (日积月累,每日三题)
  20. 函数式编程-Stream流(来源三更草堂)

热门文章

  1. 综述论文要写英文摘要吗_论文写作指导:本科学位毕业论文写作必备技巧
  2. 小度智能音箱Pro全新登场,百度软硬件结合如何青出于蓝而胜于蓝?
  3. 台式计算机性能与种类,最新台式机处理器性能排行榜
  4. php word替换换行符,word换行替换
  5. Android 广告视频循环播放 缓存 处理方案
  6. 计算机网络 谢希仁(第8版)第五章习题答案
  7. markdown温习笔记
  8. 抖音小程序开发教程之初识抖音小程序 (教程含源码)
  9. 【学习笔记】傅里叶变换: 方形函数,三角函数
  10. 网站IP更换对SEO有影响吗