数据结构---单链表
来源:互联网 发布:英国留学移民知乎 编辑:程序博客网 时间:2024/04/28 12:36
单链表是一种先行表链接存储表示。链表是由N个节点组成的,每个节点可以包括两个部分:1、数据结构体 2、指向下一个节点的指针
typedef int DataType;//node结构体typedef struct node{DataType data;struct node *Link;}ListNode;
链表相对于数组的优势是,可以在内存中随机找个空间,可以是连续的,也可以是不连续,但是要保证空间能容的下一个节点的大小。
最要在链表的第一个给一个空头,好处是把这个空头的位置定义为0,有数据的第一个定义为1,这样方便查找。
还有图个好处插入的时候可以不用管是不是头节点直接用一种方式插入就好,要是没有头节点的话,就要考虑是不是头节点的问题了。
给出两个重要的操作 增加和删除
1、增加(加入要插入到第n个位置)
增加头节点的时候只要记住:四步:
a、malloc一个节点
b、找到n-1位置上的节点
c、把第n个节点和新节点连接起来
d、把第n个和第n-1个节点断开,同时把n-1个节点个新节点连上
int Insert(ListNode *first, int i, DataType x){//备份指针ListNode *temp = first;//为新的节点分配空间ListNode *newnode = (ListNode *)malloc(sizeof(ListNode));//判断空间是否分配成功if (!newnode){printf("分配失败\n");return 0;}//给新节点赋值newnode->data = x;newnode->Link = NULL;//寻找要插入位置的前一个节点for (int count = 0; count < i-1 ; count++){temp = temp->Link;}//先把要插入节点位置原来的节点连接到新节点上,然后再把要插入节点的前一个节点和新节点连接起来newnode->Link = temp->Link;temp->Link = newnode;return 1;}
2、删除(加入要删除出第N个)
这分三步走:
a、找到第n-1个节点
b、把n-1和n+1节点连上
c、free掉节点n
void reMove(ListNode *first, int i, DataType x){//备份指针ListNode *temp = first,*pBefore,*pCurr;//判断位置是否正确if (i > getLength(first)){printf("位置错误\n");return;}//寻找要删除位置的前一个节点for (int count = 0; count < i - 1; count++){temp = temp->Link;}//确定删除节点之前的节点pBefore = temp;//确认删除的节点pCurr = temp->Link;if (pCurr->data != x){printf("请输入正确的数据\n");return;}//把要删除节点的前一个和后一个连接上pBefore->Link = pCurr->Link;//释放要删除的节点free(pCurr);}
有几个需要注意的地方:
1)定义指针时而且要使用指针指向某个结构体或者字符串的时候,需要分配内存空间大小(这个很重要,经常有人会忘记,导致段错误或者内存错误访问的错误)
2)当指针位及时被使用时需要把指针指向NULL
这个还有一个要注意:NULL就是NULL不是0地址,也不是其他的什么地址,不要勿以为是0(判断指针时候要用 p==NULL或者p !=NULL,我上面有的写的不够规范,大家见谅)
下面给出全部代码
头文件:
#ifndef _HEAD_H_#define _HEAD_H_#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR 0typedef int DataType;//node结构体typedef struct node{DataType data;struct node *Link;}ListNode;//初始化函数void initList(ListNode *first);//计算链表长度int getLength(ListNode *first);//插入函数int Insert(ListNode *first, int i, DataType x);//输出内容void outPut(ListNode *first);//删除节点void reMove(ListNode *first, int i, DataType x);//查找结点int Search(ListNode *first, DataType x);void printMsg();int getOption();#endif
函数文件
#include "head.h"void initList(ListNode *first){//如果失败就返回if (!first){printf("分配空间失败\n");return;}//把下一个节点置空,因为原则上不允许野指针,这很危险first->Link = NULL;}int getLength(ListNode *first){//备份指针,为了不影响后面的操作ListNode *temp = first->Link;int count = 0;while (temp != NULL){temp = temp->Link;count++;}return count;}int Insert(ListNode *first, int i, DataType x){//备份指针ListNode *temp = first;//为新的节点分配空间ListNode *newnode = (ListNode *)malloc(sizeof(ListNode));//判断空间是否分配成功if (!newnode){printf("分配失败\n");return 0;}//给新节点赋值newnode->data = x;newnode->Link = NULL;//寻找要插入位置的前一个节点for (int count = 0; count < i-1 ; count++){temp = temp->Link;}//先把要插入节点位置原来的节点连接到新节点上,然后再把要插入节点的前一个节点和新节点连接起来newnode->Link = temp->Link;temp->Link = newnode;return 1;}void outPut(ListNode *first){//备份指针ListNode *temp = first;//判断链表是否为空if (!temp->Link){printf("链表是空的\n");return;}//循环输出内容for (int i = 0; i < getLength(first); i++){temp = temp->Link;printf("%d ", temp->data);}printf("\n");}void reMove(ListNode *first, int i, DataType x){//备份指针ListNode *temp = first,*pBefore,*pCurr;//判断位置是否正确if (i > getLength(first)){printf("位置错误\n");return;}//寻找要删除位置的前一个节点for (int count = 0; count < i - 1; count++){temp = temp->Link;}//确定删除节点之前的节点pBefore = temp;//确认删除的节点pCurr = temp->Link;if (pCurr->data != x){printf("请输入正确的数据\n");return;}//把要删除节点的前一个和后一个连接上pBefore->Link = pCurr->Link;//释放要删除的节点free(pCurr);}int isEmpty(ListNode *first){return (first->Link == NULL) ? 1 : 0;}int Search(ListNode *first, DataType x){ListNode *temp = first;int i = 0;//判断链表是否为空if (!temp->Link){printf("链表是空的\n");return -1;}while (temp->data != x){i++;temp = temp->Link;}return i;}void printMsg(){printf("1、插入一个数据\n");printf("2、删除一个数据\n");printf("3、获得一个元素位子\n");printf("4、查看所有数据\n");printf("5、查看表是否为空\n");printf("6、退出\n");printf(">> ");}int getOption(){//获取用户输入操作 char input;scanf("%c", &input);_flushall();//fflush(stdin);//input=toupper(input); return input;}
main函数
#include "head.h"void main(void){int i,x,op;ListNode first;initList(&first);printMsg();while (op = getOption()){switch (op){case '1':printf("请输入位置和元素\n");scanf("%d %d", &i, &x);_flushall();Insert(&first,i,x);printf("插入元素%d", x);break;case '2':printf("请输入位置和元素\n");scanf("%d %d", &i, &x);_flushall();reMove(&first, i, x);printf("删除元素%d\n", x);break;case '3':printf("请输入要查找的元素\n");scanf("%d", &x);_flushall();printf("元素在%d\n", Search(&first,x));break;case '4':outPut(&first);break;case '5':printf("%d", isEmpty(&first));break;case '6':printf("---byebye----");return;break;default:break;}printf("\n>> ");}system("pause");}
程序的封装和接口的概念很重要,要尽量使用接口的封装
0 0
- 数据结构---单链表
- 数据结构--单链表
- 数据结构单链表
- 数据结构单链表
- 【数据结构】单链表
- 数据结构单链表
- [数据结构]单链表
- 数据结构--单链表
- 数据结构--单链表
- 数据结构-单链表
- 数据结构 -- 单链表
- 数据结构-单链表
- 数据结构 --- 单链表
- 数据结构---单链表
- 数据结构--单链表
- 数据结构 单链表
- 数据结构-单链表
- 数据结构---单链表
- android笔记14-Gallery
- 找出数组中有元素比它的邻居大的元素下标
- android笔记15-AlertDialog
- 通过CCID获得各个段的描述的方法
- iOS自定义控件之倒计时器
- 数据结构---单链表
- bzoj 2806: [Ctsc2012]Cheat
- 网页制作中遇到的小问题(2)
- HTML文件基本标记
- OC语言细节总结
- 怎么样判断两个工程师谁的代码能力强
- 单词数
- 8.4.3 C# 决策树
- 解决IntelliJ IDEA 安装后打开文件目录对话框不能显示中文的问题