六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 1169|回复: 0

数据结构基础之单链表

[复制链接]
 楼主| 发表于 2015-4-9 12:09:23 | 显示全部楼层 |阅读模式
数据结构基础之单链表

对单链表的建立,插入,删除,逆序,打印元素做一个小小的总结,不过我不觉得这些东西在具体的工作后到底能发挥什么作用,因为强大的STL已经把这些都做好了,我们只需要明白在什么场合使用哪一个STL就可以了。链表有一个数据域,有一个指针域,它的操作其实就是对指针域的操作,无非是指来指去而已。也许这些能反映出一个人的思维敏捷度,以及扎实的编程基础吧。

但是我想说的是这些玩意在你头脑比较清楚的时候写这个很简单,但是当你烦躁的时候,不好写吧,除非你经常写这个。单链表看着简单,但是不见得能写的正确。

该代码经过验证,测试正确,但是代码中不免有错误之处,或者哪些部分写的不好,希望高手能指出来,不胜感激。因为代码必须经过验证,那些没有经过验证的代码是不负责任的代码。在代码中我加了详细的注释。

  1. #include
  2. #include
  3. #include

  4. using namespace std;

  5. typedef struct NODE_STRU
  6. {
  7.     int data;//数据域
  8.     struct NODE_STRU *next;//指针域
  9. }NODE;

  10. //创建单链表
  11. NODE *Create()
  12. {
  13.     NODE *head, *p, *s;//head表示头结点,p表示当前节点,s表示添加的新节点
  14.     int input_data;
  15.     int cycle_flag = 1;
  16.     head = (NODE*)malloc(sizeof(NODE));//首先为头结点分配空间
  17.     p = head;//当前节点指向头结点

  18.     while(cycle_flag)
  19.     {
  20.         cout << "please input data(if input 0, cycle over!):"<< endl;
  21.         cin >> input_data;
  22.         if(0 != input_data)
  23.         {
  24.             s = (NODE*)malloc(sizeof(NODE));//为新添加的数据分配节点空间
  25.             s->data = input_data;
  26.             p->next = s;//当前节点的下一个节点指向新节点
  27.             p = s;//将当前节点指向新节点
  28.         }
  29.         else
  30.         {
  31.             cycle_flag = 0;
  32.         }
  33.     }

  34.     head = head->next;//由于头结点没有数据,使头结点指向下一个节点,即指向第一个真正的节点
  35.     p->next = NULL;//数据插入完成后,当前节点也跑到了最后,使它的下一个节点置为NULL,表示节点完成

  36.     return head;
  37. }

  38. //单链表测长,这个很简单,只需判断当前节点(初始化当前节点为头结点)是不是为空,如果不为空指向下一个节点,并计数就可以了
  39. int Length(NODE *head)
  40. {
  41.     int length = 0;
  42.     NODE *p = head;
  43.     while(p != NULL)
  44.     {
  45.         p = p->next;
  46.         length++;
  47.     }
  48.     return length;
  49. }

  50. //打印单链表,这个也很简单,在当前节点(初始化当前节点为头结点)不为空时候,打印出来,并使得当前节点指向下一个节点即可
  51. void Print(NODE *head)
  52. {
  53.     NODE *p = head;
  54.     int length = Length(head);
  55.     cout << "link length is: " << length << endl;
  56.     while(p != NULL)
  57.     {
  58.         cout << "data: " << p->data << "        ";
  59.         p = p->next;
  60.     }

  61. }

  62. //删除节点,这里的删除节点是根据节点数据进行删除的,不是从第一个节点进行删除,也不是从最后一个节点进行删除
  63. //p->next = p->next->next
  64. NODE *Del(NODE *head, int num)
  65. {
  66.     NODE *p1, *p2;//p1表示当前节点,初始化时指向头结点
  67.     p1 = head;

  68.     while(num != p1->data && p1->next != NULL)//如果当前节点的数据域与要删除的数据不相等,使当前节点指向下一个节点
  69.     {
  70.         p2 = p1;//在未找到节点时指针指向下一个节点前,先保存该节点
  71.         p1 = p1->next;
  72.     }

  73.     if(num == p1->data)//如果当前节点数据域与要删除的数据相等
  74.     {
  75.         if(p1 == head)//如果当前节点为头结点,将头结点指向当前节点的下一个节点,并释放当前节点
  76.         {
  77.             head = p1->next;
  78.             free(p1);
  79.         }
  80.         else//如果当前节点为中间节点,使当前节点指向下一个节点,注意:这里不能使用p1->next=p1->next->next,使用之前保存的节点
  81.             p2->next = p1->next;
  82.     }
  83.     else
  84.         cout << num << "can not find in link!" << endl;

  85.     return head;
  86. }

  87. //插入节点,在这里只在链表的结尾进行插入
  88. NODE *Insert(NODE *head, int num)
  89. {
  90.     NODE *p0, *p1, *p2;//p0表示新插入的节点,p1表示当前节点,初始化的时候指向头结点,p2用于保存当前节点
  91.     p1 = head;
  92.     p0 = (NODE *)malloc(sizeof(NODE));
  93.     p0->data = num;

  94.     while(p1->next != NULL)//如果当前节点的下一个节点不为空,当前节点指向下一个节点,这样当前节点最后为最后一个节点
  95.     {
  96.         p2 = p1;
  97.         p1 = p1->next;
  98.     }
  99.     p1->next = p0;
  100.     p0->next = NULL;

  101.     return head;
  102. }

  103. //进行排序,其实就是简单的冒泡排序,时间复杂度为O(n2),空间复杂度为O(1),稳定
  104. NODE *Sort(NODE *head)
  105. {
  106.     NODE *p;
  107.     if(head == NULL || head->next == NULL)
  108.         return head;

  109.     int length = Length(head);//得到链表的长度,用于遍历
  110.     for(int i=1; i<length; i++)
  111.     {
  112.         p = head;
  113.         for(int j=0; j<length-i; j++)
  114.         {
  115.             if(p->data > p->next->data)
  116.             {
  117.                 int temp = p->data;
  118.                 p->data = p->next->data;
  119.                 p->next->data = temp;
  120.             }
  121.             p = p->next;
  122.         }
  123.     }

  124.     return head;
  125. }

  126. //链表逆序
  127. NODE *Reverse(NODE *head)
  128. {
  129.     if(head == NULL || head->next == NULL)
  130.         return head;
  131.     //这样来实现,在链表中一次从链表尾删除节点,然后在新建立的链表中插入节点(尾插法)
  132.     int length = Length(head);
  133.     int a[length];
  134.     int i = 0;
  135.     NODE *p = head;
  136.     while(p != NULL)
  137.     {
  138.         a[i] = p->data;
  139.         i++;
  140.         p = p->next;
  141.     }

  142.     for(int j=0; j<length; j++)="" 暂时用于测试
  143.         cout << j << ":" << a[j]<<"";

  144.     NODE *newhead, *link, *s;
  145.     newhead = (NODE *)malloc(sizeof(NODE));
  146.     link = newhead;
  147.     for(int k=length-1; k>=0; k--)
  148.     {
  149.          s = (NODE *)malloc(sizeof(NODE));
  150.          s->data = a[k];
  151.          link->next = s;
  152.          link = s;
  153.     }
  154.     newhead = newhead->next;
  155.     link->next = NULL;

  156.     return newhead;
  157. }

  158. //求单链表的中间节点
  159. void SearchMid(NODE* head)
  160. {
  161.     cout << "head data: " << head->data<< "";
  162.     NODE *tmp1 = head;
  163.     NODE *tmp2 = head;
  164.     NODE *mid;
  165.     while(tmp1->next != NULL && tmp1->next->next != NULL)
  166.     {
  167.         tmp1 = tmp1->next->next;
  168.         tmp2 = tmp2->next;
  169.         cout << "tmp1:" << tmp1->data<< ",tmp2:" << tmp2->data<<"";
  170.     }
  171.     mid = tmp2;
  172.     cout << "SearchMid mid data: " << mid->data;
  173. }

  174. int main(int argc, char *argv[])
  175. {
  176.     cout << "create link..." << endl;
  177.     NODE *p = Create();
  178.     cout << "print link..." << endl;
  179.     Print(p);

  180.     int delnode;
  181.     cout << "input delete node: ";
  182.     cin >> delnode;
  183.     cout << "delete node " << delnode << endl;
  184.     Del(p, delnode);
  185.     cout << "print link..." << endl;
  186.     Print(p);

  187.     cout << "insert link...";
  188.     Insert(p, 20);
  189.     Print(p);

  190.     cout <<"sort from low to high...";
  191.     Sort(p);
  192.     Print(p);

  193.     cout << "reverse...";
  194.     NODE *revlink = Reverse(p);
  195.     Print(revlink);

  196.     cout << "find mid node data...";
  197.     SearchMid(p);

  198.     return 0;
  199. }
复制代码

运行结果:


数据结构基础之单链表

摘自:http://blog.csdn.net/feitianxuxue/article/details/9989591

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博账号登陆

x
该会员没有填写今日想说内容.
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表