加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

C语言难点总结(二)----链表

(2010-06-19 00:00:00)
标签:

c语言

链表

通讯簿

通讯录

分类: IT技术
       链表是学习C语言的最后一个内容,也是最难的一个部分,它分为有头节点的链表和没有头节点的链表,这两种情况演绎出了完全不同的增、删、改、查函数和创建链表、删除链表函数。为了能够阐述明白,我将在这里分两次说清楚,另外,需要特别提醒的是:学习程序必须要动手,光看不练可不行哦!

这篇文章主要介绍带头节点的链表:

       首先要说说带头节点的链表原理,带头节点的链表和不带头节点的链表的各个节点都是由结构体组成的,链表中充当节点角色的结构体理论上分为两个部分,分别是数据域和指针域,顾名思义,数据域就是节点中的数据,指针域就是用来链接节点,形成链表关系的指针。例如,有这样的题目:
===================================================================
       请运用结构体和动态链表建立图书查询程序,图书信息包括图书ISBN号、书名、作者、书价。要求程序具有如下功能:
             1、从键盘上接收数据建立链表;
             2、根据书名进行查询;
             3、打印出链表中的所有书籍信息;
             4、删除一本已有的图书;
             5、添加一本新图书

===================================================================
          链表节点的结构体请参照下图:

        所谓带有头节点的链表是指第一个节点中只有指针域有意义,数据域没有意义,其他的节点数据域存储相应的数据信息,指针域建立链接关系,它的原理示意图如下,注意最后一个节点的指针要置为NULL:
http://s8/middle/66ec4d66g8a7278fda377&690链表的产生弥补了数组的诸多缺点,比如,数组在添加新元素时,如果添加的位置是数组的首部或者数组中间,那么,程序员不得不设计算法移动数组的相关元素,而且往往涉及的相关元素很多;再比如从数组中删除一个元素,如果删除的不是尾部元素,那么同样会去移动其他元素,从而大大影响程序的整体效率,正基于此,链表才得以应运而生,不过链表也有先天的缺陷和短处,在搜索或随机读写内部元素的时候就远远不如数组了,所以使用时要因地制宜,对症下药。
上一段说了链表比数组在添加删除元素的时候具有优越性,那么为什么具有这些优越性呢?请看下图:
http://s9/middle/66ec4d66g8a73b257f998&690=============================================================
根据上图如果要删除符合条件的节点(删除q所指节点)

1、首先找到要删除节点的前驱节点  if(p->next->data满足条件)
2、用q指向要删除的节点    q = p->next;
3、p->next = q->next;
4、free(q);
===================================================================

下图为给链表添加节点的示意图:
http://s5/middle/66ec4d66g743ec62b7a74&690==================================================================
根据上图所示,在第i个节点之前插入一个节点
1、首先查找第i-1个节点   if(p满足条件)
2、给新节点分配空间q =(Node*)malloc(sizeof(Node));给q数据域赋值。
3、q->next = p->next;
4、p->next = q;
==================================================================

上面是对链表原理的解释和说明,下面通过完整的代码来说明:
==================================================================
题目要求如下:
用链表实现通讯录的功能,要求:
1、创建具有头节点的链表通讯录。
2、可以从链表通讯录尾部插入节点(为初学者方便起见)。
3、可以删除指定的节点信息。
4、可以遍历链表通讯录的所有节点。
==================================================================

下图为项目的文件结构:

http://s10/middle/66ec4d66g8a73faeb8979&690==================================================================
//文件名:notebook.h

#ifndef NOTEBOOK_H
#define NOTEBOOK_H

#define KNAME_SIZE 20
#define KPHONE_NUMBER_SIZE 12
typedef int BOOL;


typedef struct notebook
{
    char name[KNAME_SIZE];
    char phoneNumber[KPHONE_NUMBER_SIZE];

    struct notebook *next;
}noteBook;

//创建链表
extern noteBook *createBook(void);

//从链表尾部插入数据
extern BOOL insertRecord(noteBook *aHead, char *aName, char *aPhoneNumber);

//从链表中删除节点,删除纪录时指定该条记录的名字
extern BOOL deleteRecord(noteBook *aHead, char *aName);

//遍历链表
extern void showBook(noteBook *aHead);

//销毁链表
extern void destroyBook(noteBook *aHead);

#endif
===================================================================


===================================================================
//文件名:notebook.cpp

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "notebook.h"

#define TRUE  1
#define FALSE 0

//创建链表
noteBook *createBook(void)
{
    noteBook *head = NULL;
    head = (noteBook *)malloc(sizeof(noteBook));
    head->next = NULL;

    return head;
}

//从链表尾部插入数据
BOOL insertRecord(noteBook *aHead, char *aName, char *aPhoneNumber)
{
    noteBook *p = NULL;

    p = (noteBook *)malloc(sizeof(noteBook));
    if(NULL == p)
    {
        printf("failed...\n");
        return FALSE;
    }
    strcpy(p->name, aName);
    strcpy(p->phoneNumber, aPhoneNumber);
    p->next = NULL;
    while(aHead->next)
    {
        aHead = aHead->next;
    }
    aHead->next = p;
    return TRUE;
}

//从链表中删除节点,删除纪录时指定该条记录的名字
BOOL deleteRecord(noteBook *aHead, char *aName)
{
    while(aHead->next)
    {
        if(!strcmp(aHead->next->name, aName))
        {
            noteBook *temp = aHead->next;
            aHead->next = aHead->next->next;
            free(temp);
            return TRUE;
        }
        aHead = aHead->next;
       
    }

    return FALSE;
}

//遍历链表
void showBook(noteBook *aHead)
{
    while(aHead->next)
    {
        aHead = aHead->next;
        printf("%s, %s \n", aHead->name, aHead->phoneNumber);
    }
}

//销毁链表
void destroyList(noteBook *aHead)
{
    noteBook *p = aHead->next;

    while(p)
    {
        free(aHead);
        aHead = p;
        p = p->next;
    }
    free(aHead);

}

===================================================================

===================================================================
//文件名:demo.cpp

#include <stdio.h>
#include <stdlib.h>
#include "notebook.h"

int main(void)
{
    noteBook *head = NULL;

    head = createBook();
   
    insertRecord(head, "zhangsan", "13833335555");
    insertRecord(head, "lisi", "15866668888");
    insertRecord(head, "wangwu", "13322229999");

    showBook(head);
    printf("\n---------------------\n");
    deleteRecord(head, "zhangsan");

    showBook(head);

    destroyList(head)

    system("pause");
    return 0;
}

===================================================================

以上程序说明了,链表程序的一般写法和一般使用方法,其中关于插入纪录的方法还有更多发挥空间,希望我的文章可以抛砖引玉。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有