牢骚:本篇博客两个星期前已经存为草稿,鉴于发生一些糟糕的事情,今天才基本完成。本人6月份应届毕业生一枚,毕业后当天来到帝都,之后也非常顺利,面试了俩家公司都成功了。一家做C++方面电商ERP,一家做wifi模块,觉得第二家公司小,薪资低,但是觉得好玩就去了。同时,在学校也喝了不少鸡汤,觉得公司小怎么了。然而去了不到20天,公司被深圳一家公司收购了,公司动员我去深圳,我尼玛我才来20多天啊,有木有?而且感觉公司做这么大的决定都是随时拍板的吗?

原本以为一个公司的生命力强到可以忽略的概率,然而当自己真实的遇到这一切,才知道这个社会有多残忍,公司的生存可能比一个员工的生存更要困难。

接下来就是找工作了,跑呀,找呀。。。。。。。。           一路被忽略,一路被放鸽子,一路被无视。。。。。。。   心里五味杂陈。。。。。。。。。

so,可能我还是太菜了,这种玩计算机的心态,也许会被生活玩,唯有认真拼命的学习也许能够拯救我的颓势。

感谢seven,严厉也好,鼓励也好,短短的一个月,您教会了我许多,感谢您的知遇之恩!愿你们去深圳一切顺利!待倔强的我在北京玩上一阵!

————————————————————————————————————————————————————————————————————————————————

链表是数据结构中比较基础也是比较重要的类型之一,那么有了数组,为什么我们还需要链表呢!或者说设计链表这种数据结构的初衷在哪里?

这是因为,在我们使用数组的时候,需要预先设定目标群体的个数,也即数组容量的大小,然而实时情况下我们目标的个数我们是不确定的,因此我们总是要把数组的容量设置的很大,这样以来就浪费了很多的空间。另外,数组在进行插入操作和删除操作的时候,在插入或者删除制定元素之后,我们往往需要进行循环移位,这增加了我们的线性开销。

正是由于以上的两种主要原因,链表被设计出来用于一般表的操作。为了避免上面描述数组的两种弊端,我们希望链表有一下的特点

1 可以灵活的扩展自己的长度。

2 存储地址不连续,删除或者插入操作的时候不需要循环移位。

要实现以上两个特点,我们需既要保证每个节点的独立性,又要保存相邻两个节点的联系。

为此,链表一般被设计为下面的形式。

Node--->Node---->Node

链表是由一个一个的节点组成的,可以方便和自由的插入未知个Node,前一个节点中用指针保存着下一个节点的位置,这样以来便顺利的完成了我们对链表的两点期望,但是唯一的缺点是增加了额外的空间消耗。

————————————————————————————————————————————————————————————————————————————

链表的定义:

链表的定义一般使用结构体,在看《数据结构与算法分析》这本书的时候发现,书中频繁的使用typedef的关键字,结果真的很棒不仅保持的代码的整洁程度,也让我们在下面的编码过程中少见了很多烦人的指针(当然指针还是一直存在的)。所以这里也借用了书中的定义方法。

struct Node;
typedef struct Node* PtrNode;
typedef PtrNode Position;
typedef PtrNode List;
struct Node{
int Value;
PtrNode Next;
};

下面接着书写一个建立链表的函数,输入每个节点的值,直到这个值是-1的时候函数结束。

在这个里面,我以前一直搞不明白为什么需要定义三个Node *,现在终于了解了,最终还是复习了指针的内容明白的,这里说一下指针实现链表对指针的操作很频繁,需要比较扎实的掌握了指针之后,在来看链表会轻松很多。在下面的一段程序里,我分别定义了head/p/tmp这三个指向节点结构体的指针,head的主要作用就像一个传销头目,他会主动联系上一个下线p,然后他就什么也不干了,p接着去发展一个又一个的下线tmp,结果一串以head为首的链表就出来了。

起先,我总觉得有了head,为什么还要p,这是因为如果直接使用head去指向下一个节点,head的位置也是不断在移动的,即它永远处于链表的尾端,这样当我们返回链表的时候,其实是空值。所以,我们需要p这个中转环节。(其实,这种做法在指针中非常普遍,大部分有返回指针类型的函数中,都会首先定义一个指针变量来保存函数的传入的参数,而不是对参数直接进行操作)。

/*
函数功能:创建一个链表
函数描述:每次输入一个新的整数,即把新增加一个节点存放该整数,
当输入的整数为-1时,函数结束。
*/
List create()
{
int n=;
Position p,head,tmp;
head=NULL;
tmp=malloc(sizeof(struct Node));
if(tmp==NULL)
{
printf("tmp malloc failed!\n");
return NULL;
}
else
{
p=tmp;
printf("please input the first node's message!\n");
scanf("%d",&(tmp->Value));
}
while(tmp->Value!=-)
{
n+=;
if(n==)
{
head=p;
tmp->Next=NULL;
}
else
{
p->Next=tmp;
}
p=tmp;
tmp=malloc(sizeof(struct Node));
printf("please input the %d node!\n",n+);
scanf("%d",&(tmp->Value));
}
p->Next=NULL;
free(tmp); //free函数free掉的只是申请的空间,但是指针还是依然存在的。
tmp=NULL;
return head; }

接下来,在写一个删除链表节点的函数,输入一个整数然后遍历链表节点,当链表节点的值与该整数相等的时候,即把该节点删除。

在完成这个函数首先一定要把这个过程思考清楚,不可否认我之前是一个上来就敲代码的人,看了《剑指offer》感觉这种习惯是程序员的大忌,甚至还想写一篇博客,名字都想好了《程序员的自我修养之思考在前,代码在后》。其实想想也是,我们写程序的目的是为了解决问题,而不是为了简单的写程序,纯粹的让程序跑起来大概只会在上学那会存在吧!真实的程序开发中需要考虑几乎所有 能想到的实际问题,所以无论程序再下,一要学会先思考清楚,再下笔写程序。

关于这个函数,我们要想到的是:

1 如果链表为空,我们该怎么做,当然是直接返回。

2 如果要删除的元素为头节点该怎么办?

3 如果要删除的元素为尾节点该怎么办?

当注意到以上三个部分,我们的程序就可能避免掉了输入链表为空,程序直接崩溃的现象,也可以避免删除元素值为头节点时删不掉的尴尬。我们的程序就有了一定的鲁棒性。

下面着重考虑链表的删除的实现:

list:      Node_a->Node_b->Node_c->Node_d;

list        tmp         p

------->              tmp->Next=p->Next;

list:       Node_a->Node_b----------->Node_d

free(p)

假设我们要删除的节点为上图的Node_c;假设我们能够找到Node_c的前一个位置tmp和被删除节点位置p的话;这个时候我们只需要执行tmp->Next=p->Next即可。

只要完成上面的分析以及考虑到各种情况,我们完成下面的代码就水到渠成了。

/*
函数功能:删除链表中指定值的节点(如果存在多个,只删除第一个)
本例中输入一个整数,删除链表节点值为这个整数的节点。
*/
List DeleteNode(List list)
{
Position p,tmp;
int value;
if(list==NULL)
{
printf("The list is null,function return!\n");
return NULL;
}
else
{
printf("please input the delete Node's value:\n");
scanf("%d",&value);
}
p=list;
if(p->Value==value)
{
list=p->Next;
free(p);
p=NULL;
return list;
}
while(p!=NULL&&p->Value!=value)
{
tmp=p;
p=p->Next;
}
if(p->Value==value)
{
if(p->Next!=NULL){
tmp->Next=p->Next;
}
else
{
tmp->Next=NULL;
}
free(p);
p=NULL;
}
return list; }

关于链表的使用场景分析:

链表在程序开发中用到的频率还是非常高的,所以在高级语言中往往会对链表进行一些实现,比如STL中list以及Java中也有类似的东西。在目前的服务器端开发,主要运用链表来接收一些从数据中取出来的数据进行处理。

即使你不知道链表的底层实现,仍然可以成功的运用STL里面的现成的东西。但是作为一个学习者,我觉得会使用和从底层掌握仍然是两个不同的概念,linux之父说:“talk is less,show you code”。

以下的程序,用链表模拟了一个电话通讯录的功能,包括添加联系人,查找联系人,以及删除联系人。

PS:关于鲁棒性,程序中最大的危险是使用了gets这个函数,目前先保留使用gets,等待找到工作之后在做进一步的程序完善。

/**************************************************************************
Programe:
This is a phone list write by list
The programe is just prictise for list
Author: heat nan
Mail:964465194@qq.com
Data:2015/07/27
**************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 25
#define M 15
struct node;
typedef struct node* p_node;
typedef p_node List;
typedef p_node Position;
typedef struct node** PList;
struct node{
char name[N];
char number[M];
Position next;
};
int JudgeNameExist(List list,char* name);
void AddPerson(PList list);
void PrintList(List list);
List FindPerson(List list);
List FindPersonByName(List list,char* name);
int AddPersonByName(PList list,List node);
int DeletePersonByName(PList list,char* name);
void DeletePerson(PList list);
int main()
{
List list=NULL;
Position p;
char cmd[];
while()
{
printf(" MAIN \n");
printf(" ******* 1 add a person *******\n");
printf(" ******* 2 show the phone list *******\n");
printf(" ******* 3 find from phone list *******\n");
printf(" ******* 4 delete from phone list *******\n\n\n");
printf("Please input the cmd number:\n");
gets(cmd);
switch(cmd[])
{
case '':
AddPerson(&list);
break;
case '':
PrintList(list);
break;
case '':
FindPerson(list);
break;
case '':
DeletePerson(&list);
break;
default:
printf("wrong cmd!\n");
break; } }
return ;
}
/*
Function:判断要添加的联系人名称是否已经存在于电话簿中.
Input: List 电话列表,name 要添加的联系人的姓名.
Return: 已经存在返回1,不存在返回0.
*/
int JudgeNameExist(List list,char* name)
{
if(FindPersonByName(list,name)!=NULL)
return ;
else
return ;
}
/*
Function:根据输入的姓名查找联系人的信息节点
Input: 要输入的电话列表list,姓名name
Return: 返回查找到的节点
*/
List FindPersonByName(List list,char* name)
{
while(list!=NULL)
{
if(strcmp(list->name,name)==)
break;
list=list->next;
}
return list;
}
/*
Function:根据姓名添加新的联系人到联系人列表
Input: 指向联系人列表地址的指针, 新用户节点
Return: 添加成功返回1,添加失败返回0
*/
int AddPersonByName(PList list,List node)
{
if(node==NULL)
{
printf("the node is NULL!\n");
return ;
}
if(*list==NULL)
{
*list=node;
return ;
}
List pHead=*list;
while(pHead->next!=NULL)
pHead=pHead->next;
pHead->next=node;
return ;
}
void AddPerson(PList list)
{
Position tmp;
Position p_head;
tmp=(struct node*)malloc(sizeof(struct node));
char name[N];
char number[M];
if(tmp==NULL)
{
printf("malloc the tmp node failed in function add person!\n");
}
else
{ printf("please input the name:\n");
gets(name);
printf("please input the number:\n");
gets(number);
strcpy(tmp->name,name);
strcpy(tmp->number,number);
tmp->next=NULL;
}
if(JudgeNameExist(*list,name)==)
{
free(tmp);
printf("the name have already exist!\n");
return;
}
AddPersonByName(list,tmp);
}
/*
Function: 打印联系人列表
Input: 联系人列表 */
void PrintList(List list)
{
Position show;
show=list;
if(show==NULL)
{
return ;
}
printf("Now,we print the phone list:\n");
while(show!=NULL)
{
printf("Name:%s Number:%s\n",show->name,show->number);
show=show->next;
} }
List FindPerson(List list)
{
char name[N];
Position pHead=list;
printf("please input the name you will find:\n");
gets(name);
Position node=FindPersonByName(list,name); if(node!=NULL)
printf("find success! name-> %s number-> %s\n",node->name,node->number);
else
printf("find failed!\n");
return node;
}
/*
Function:根据姓名删除联系人
Input: 指向联系人地址的指针,联系人姓名
Output: 删除成功返回1,失败返回0
*/
int DeletePersonByName(PList list,char* name)
{
if(*list==NULL||name==NULL)
return ;
List pHead=*list;
if(strcmp(pHead->name,name)==)
{
*list=pHead->next;
free(pHead);
pHead->next==NULL;
return ;
}
List tmp=pHead->next;
while(tmp!=NULL)
{
if(strcmp(tmp->name,name)==)
{
pHead->next=tmp->next;
free(tmp);
tmp->next=NULL;
return ;
}
pHead=tmp;
tmp=tmp->next;
}
return ; }
void DeletePerson(PList list)
{
List pHead=*list;
if(pHead==NULL)
{
printf("there is no person you can delet\n");
return ;
}
char name[N];
printf("please input the name:\n");
gets(name);
DeletePersonByName(list,name);
}

数据结构之链表C语言实现以及使用场景分析的更多相关文章

  1. 数据结构与算法分析——C语言描述 第三章的单链表

    数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...

  2. C语言数据结构-单链表的实现-初始化、销毁、长度、查找、前驱、后继、插入、删除、显示操作

    1.数据结构-单链表的实现-C语言 typedef struct LNode { int data; struct LNode* next; } LNode,*LinkList; //这两者等价.Li ...

  3. 《数据结构与算法分析——C语言描述》ADT实现(NO.00) : 链表(Linked-List)

    开始学习数据结构,使用的教材是机械工业出版社的<数据结构与算法分析——C语言描述>,计划将书中的ADT用C语言实现一遍,记录于此.下面是第一个最简单的结构——链表. 链表(Linked-L ...

  4. 数据结构与算法C语言实现笔记(1)--表

    声明:此一系列博客为阅读<数据结构与算法分析--C语言描述>(Mark Allen Weiss)笔记,部分内容参考自网络:转载请注明出处. 1.表 表是最简单的数据结构,是形如A1.A2. ...

  5. 数据结构算法集---C++语言实现

    //数据结构算法集---C++语言实现 //各种类都使用模版设计,可以对各种数据类型操作(整形,字符,浮点) /////////////////////////// // // // 堆栈数据结构 s ...

  6. linux内核数据结构之链表

    linux内核数据结构之链表 1.前言 最近写代码需用到链表结构,正好公共库有关于链表的.第一眼看时,觉得有点新鲜,和我之前见到的链表结构不一样,只有前驱和后继指针,而没有数据域.后来看代码注释发现该 ...

  7. 链表c语言实现

    链表(c语言实现)--------------小练习   #include <stdio.h> #include <stdlib.h> #include <string. ...

  8. redis 系列4 数据结构之链表

    一. 概述 链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可能通过增删节点来灵活地调整链表的长度.作为一种数据结构,在C语言中并没有内置的这种数据结构.所以Redis构建了自己的链表实现 ...

  9. 用Python实现数据结构之链表

    链表 链表与栈,队列不一样,它是由一个个节点构成的,每个节点存储着本身的一些信息,也存储着其他一个或多个节点的引用,可以从一个节点找到其他的节点,节点与节点之间就像是有链连在一起一样,这种数据结构就叫 ...

随机推荐

  1. mysql、sql server、oracle数据库分页查询及分析(操作手册)

    1.mysql分页查询 方式1: select * from table order by id limit m, n; 该语句的意思为,查询m+n条记录,去掉前m条,返回后n条记录.无疑该查询能够实 ...

  2. sql date时间加减几天几小时

    //时间转成年月日时分秒select date_format(now(),'%Y%m%d%H%i%S')//时间转成年月日select date_format(now(),'%Y%m%d')//去年此 ...

  3. Linux shell misc

    sometimes you will write shell in windows platform, be careful for this, adjust the notepad plus plu ...

  4. 【读书笔记《Android游戏编程之从零开始》】1.Android 平台简介与环境搭建

    简单的记录下笔记,具体可百度! Android SDK (Software Development Kit)- Android 软件开发工具包,用于辅助Android 操作系统软件开发,是开发Andr ...

  5. A*算法详解 BZOJ 1085骑士精神

    转载1:A*算法入门 http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx 在看下面这篇文章之前,先介绍几个理论知识,有助于理解A*算 ...

  6. [cocos2dx]利用NDK崩溃日志查找BUG

    摘要: 在android上开发c++应用, crash日志都是汇编码, 很难对应到c++代码中去. 通过此文, 你可以定位到程序崩溃时的C++代码, 精确查找问题. 博客: http://www.cn ...

  7. 2014 Super Training #9 E Destroy --树的直径+树形DP

    原题: ZOJ 3684 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3684 题意: 给你一棵树,树的根是树的中心(到其 ...

  8. IO流的练习2 —— 复制单级文件夹中的文件

    需求:把C:\Users\Administrator\Desktop\记录\测试里面的所有文件复制到 C:\Users\Administrator\Desktop\新建文件夹\copy文件夹中 分析: ...

  9. 【转】【WPF】WPF 登录窗口关闭时打开主窗口

    在WPF中设计登录窗口关闭时打开主窗口,自动生成的App.xaml不能满足要求, 1.把App.xaml的属性窗口中的生成操作设定为 无 2.添加Program类 static class Progr ...

  10. 携手K2 BPM,华住酒店完美实现“互联网+”转型

    华住酒店集团,旗下6大品牌酒店,包括商旅品牌—禧玥酒店.全季酒店.星程酒店.汉庭酒店.海友酒店,以及度假品牌—漫心度假酒店.高端大气上档次一气呵成,2013年签约K2,携手成就美好生活. 演讲人:宋洪 ...