链表的操作

原创 2004年09月13日 13:07:00

    链表,是数据结构的基础。利用链表,我们可以很好的实现数据的管理。但是我们经常在网上看见各式各样的有关链表的问题,在此我给出了一个比较简单但是功能比较强大的程序来给大家显示关于链表的编程。如果你很深入的了解了下面程序的工作原理,说明你对链表的理解就算过关了,如果不能,请仔细阅读一下下面的程序,特别注意程序指针的修改顺序。 特别是链表的倒置程序,不超过10行就搞定了,还没有额外的申请空间,何乐而不为? 程序在VC6下调试编译通过

#include <stdio.h><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

#include <malloc.h>

#include <string.h>

#include <conio.h>

 

/* 书中的常量定义 */

#define OK       1

#define ERROR    0

#define OVERFLOW (-1)

 

typedef int Status;

 

/* 定义了一个学生的结构体 */

typedef struct {

     int sn;          /* 学号 */

     char name[32]; /* 姓名 */

     int score;      /* 成绩 */

} data_t;

 

/* 定义了链表的节点形式为一个单链表 */

typedef struct LNODE {

     data_t data;

     struct LNODE * next;

}node_t, *link_t;

 

/* 创建一个有头节点的链表 */

link_t create_link();

 

/* 销毁链表,释放节点空间 */

void   destroy_link(link_t head);

 

/* 在链表的第 idx 位置插入一个节点,节点的值由 d 给出*/

/* 注意 idx 为插入节点后的位置,且从0开始计算 */

Status insert_node(link_t head, int idx, data_t e);

 

/* 删除链表的第 idx 个节点,并将删除的内容填入e所指向的空间*/

/* idx也是从0开始计算 */

Status delete_node(link_t head, int idx, data_t* e);

 

 

/* 判断链表是否为空 */

Status empty_link(link_t head);

 

/* 获得链表的长度 */

int  length_link(link_t head);

 

/* 获得链表的第i个元素的位置,并返回执行该元素的指针,NULL表示无效 */

node_t* locate_link(link_t head, int idx);

 

/* 打印链表的内容 */

void print_link(link_t head);

 

/* 将一个链表倒置 */

void reverse_link(link_t head);

 

/* 键盘命令映射表 */

const char *help[] =

{

     "?,h,H   -- this help/n",

     "a,A,i,I -- add a node, ex: a 10/n",

     "d,D      -- del a node, ex: d 10/n",

     "p,P      -- print this link/n",

     "g,G      -- get link num/n",

     "r,R      -- reverse the link/n",

     "x,X,q,Q -- exit this program/n",

};

 

/* 程序入口 */

int main(int argc, char* argv[])

{

     char cmd;

     int i, idx;

     data_t tmp;

 

     link_t head = create_link();

     for (i=0; i<10; i++)     { /*预先插入10个节点*/

         tmp.sn = i; tmp.score = 100-i; strcpy(tmp.name, "ttttt");

          insert_node(head, i, tmp);

     }

     print_link(head);

     printf("input command: ");

     while ( cmd = getch())

     {

          printf("%c/n", cmd);

         switch (cmd)

         {

         case '?': case 'h':     case 'H': /*打印帮助信息*/

              for (i=0; i<sizeof(help)/sizeof(help[0]); i++)

                   printf("/t%s", help[i]);

              printf("/n");

              break;

         case 'a': case 'A':     case 'i': case 'I': /*插入一个节点*/

              printf("please input where do you want to insert: ");

              scanf("%d", &idx);

              if (idx < 0 || idx > length_link(head))   {

                   printf("insert pos error!/n");

                   break;

              }

              printf("please input the SN, name and score:");

              scanf("%d%s%d", &tmp.sn, tmp.name, &tmp.score);

              if (insert_node(head, idx, tmp) == ERROR){

                   printf("insert error!/n");

                   break;

              }

              printf("insert OK!/n");

              print_link(head);

              break;

         case 'd': case 'D': /*删除一个节点*/

              printf("please input which do you want to delete: ");

              scanf("%d", &idx);

              if (idx < 0 || idx >= length_link(head))   {

                   printf("delete pos error!/n");

                   break;

              }

              if (delete_node(head, idx, &tmp) == NULL) {

                   printf("input error!/n");

                   break;

              }

              printf("delete OK/n");

              print_link(head);

              break;

         case 'p': case 'P': /* 打印链表*/

              print_link(head);

              break;

 

         case 'x': case 'X':     case 'q':     case 'Q':/*退出程序*/

              destroy_link(head);

              return 0;

         case 'r': case 'R': /*倒置链表*/

              reverse_link(head);

              printf("this link have been reversed!/n");

              print_link(head);

              break;

          default:

              printf("input error!, for help, please input ?/n");

         }

          printf("/n/ninput command: ");

     }

 

     return 0;

}

 

link_t create_link()

{

     link_t head;

     head = (link_t)malloc(sizeof(node_t));

     head->next = NULL;

     head->data.sn = 0;

     return head;

}

 

void   destroy_link(link_t head)

{

     node_t *p = head;

     while (head != NULL) {

         p = head->next;

         free (head);

         head = p;

     }

}

void   print_link(link_t head)

{

     node_t *p = head->next; /*跳过头节点*/

     int cnt = 0;

    printf("pos :  SN %20s score/n", "name      ");

     while (p != NULL) {

          printf("%04d: %4d%20s%4d/n",

cnt++, p->data.sn, p->data.name, p->data.score);

         p = p->next;

     }

}

 

Status   empty_link(link_t head)

{

     if (head==NULL || head->next == NULL)

         return OK;

     else

         return ERROR;

}

 

int   length_link(link_t head)

{

     int len = 0;

     node_t *p = head->next;

     for(; p!=NULL; p = p->next)

len++;

     return len;

}

 

node_t* locate_link(link_t head, int idx)

{

     int pos = -1;

     node_t *p = head;

     while (p!=NULL && pos < idx) {

         p = p->next; pos ++;

     }

     return p;

}

 

 

Status insert_node(link_t head, int idx, data_t e)

{

     node_t *add = NULL; /* 待加入的节点指针 */

     node_t *p = locate_link(head, idx-1); /*注意查询idx-1*/

    if (p == NULL) return ERROR;

 

     add = (node_t *)malloc(sizeof(node_t));

     add->data = e;

     add->next = p->next;

     p->next = add;

     return OK;

}

 

Status delete_node(link_t head, int idx, data_t *e)

{

     node_t *p = locate_link(head, idx-1); /*注意查询idx-1*/

     node_t *q = NULL; /* p为待删除的节点指针 */

     if (p == NULL || p->next== NULL) return ERROR;

     q = p->next;

    

     *e = q->data;

     p->next = q->next;

     free (q);

     return OK;

}

 

void reverse_link(link_t head)

{

     node_t *p1, *p2;

     p1 = head->next;

     head->next = NULL;

    

     while (p1 != NULL)    {

         p2 = p1->next;

          p1->next = head->next;

          head->next = p1;

         p1 = p2;

     }

}

 

    大家看见了,上面的每一个子函数都很简单,不超过10行。唯一的只有main函数比较长。而main函数却实现了一个常用的菜单操作的示例,包括帮助、链表的插入、删除等功能的命令与功能实现的对应,也是各个函数功能组合为各种具体功能的实现。

 

 ——小儿科,大家别扔砖头,鸡蛋可以!

C语言系列之 链表与相关操作

清华大学尹成老师、微软全球最具价值专家,带你步入 C 语言的殿堂,讲课生动风趣、深入浅出,全套视频内容充实,整个教程以 C 语言为核心,完整精彩的演练了数据结构、算法、设计模式、数据库、大数据高并发检索、文件重定向、多线程同步、进程通讯、黑客劫持技术、网络安全、加密解密,以及各种精彩的小项目等,非常适合大家学习!
  • 2015年06月26日 11:26

数据结构——循环链表的操作3

  • 2011年09月27日 22:51
  • 2KB
  • 下载

链表建立、删除、插入基本操作

在数据结构中,链表无疑是最基本的,也是在大多数IT公司面试笔试中考察最多的;有了扎实的处理链表的基础,对以后学习更复杂的数据结构类型是很有帮助也是很有必要的;因此在闲暇时间中,又再一次重写了对于链表的...
  • wenhai_zh
  • wenhai_zh
  • 2013-07-29 12:05:07
  • 3126

数据结构之链表基本操作总结

数组与链表的区别  数组(顺序存储)和链表(链式存储)是两种不同的数据存储方式。 数组是一组具有相同类型和名称的变量的集合,这些变量称为数组的元素,每个数组元素都有一个编号,这个编号称...
  • Lily_whl
  • Lily_whl
  • 2017-05-11 18:22:11
  • 2578

链表的基本操作之插入、删除、逆置

提到链表,无非就是指针指来指去,最终连成一个链。好多人困惑的地方就在于p->next=r->next,指针到底是如何指向的,弄清楚这个,删、查、排的操作也就很容易弄懂了。...
  • i_am_what_i_am
  • i_am_what_i_am
  • 2016-05-29 15:48:45
  • 2243

顺序链表的常用操作实现及注意事项

在知乎看了轮子哥,又加强了我对编程的热情,编程方面还是个雏,一步一步来吧。 自己理解顺序结构有几点好处,查找方便,不好之处便是删除添加移动的元素挺多的。 需要注意的两点, 删除 添加时 主...
  • J3286056707
  • J3286056707
  • 2016-11-15 01:23:01
  • 261

多线程安全链表操作的C程序

  • 2015年12月04日 00:03
  • 6KB
  • 下载

Java数组和链表两种结构的操作效率,在哪些情况下,哪些操作的效率高

首先这个问题,没有固定答案,全看个人理解,毕竟这2个的数据结构,大家肯定都是知道的。能有如下回答,基本就够用啦。 数组: 数组就像一个班级一样,一旦分完班,一个班多少人,每个人的学号啥的都是确定的啦...
  • qq_27093465
  • qq_27093465
  • 2016-08-21 16:19:41
  • 5073

java 链表的常见操作

1.定义链表的节点类 class Node { protected Node next; // 下一节点 protected String data;// 数据 public Node(St...
  • kangaroo_07
  • kangaroo_07
  • 2017-08-30 21:53:04
  • 1122

c++链表实例与链表基本知识

我们知道,数组是事先定义好的数组类型与长度 自动为其分配的一连续的存储单元相同数组的位置和距咯是固定的因此可以对数组元素进行随机访问。但若对数组元素进行插入和删除操做,则会引起大量的数据移动,从而使数...
  • qq_23301703
  • qq_23301703
  • 2015-07-13 16:02:48
  • 910
收藏助手
不良信息举报
您举报文章:链表的操作
举报原因:
原因补充:

(最多只允许输入30个字)