链表操作二——中间结点的删除等

一:特殊要求的结点删除

问题描述:假设有一个没有头指针的单链表。一个指针指向此单链表中间的一个结点(不是第一个,也不是最后一个)。请将该节点从单链表中删除。

思路:根据题意,似乎很难完成。其实我们可以将当前结点的后续结点的值域赋值给当前结点的值域。然后再删除当前结点的后续结点,即可完成”狸猫换太子“。代码如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <time.h>
 5 
 6 typedef struct tag
 7 {
 8     int Nnum_;
 9     struct tag *Nnext_;
10 }Node, *pNode;
11 
12 
13 void link_print(pNode phead)
14 {
15     while(phead != NULL)
16     {
17         printf("%4d", phead->Nnum_);
18         phead = phead->Nnext_;
19     }
20     printf("\n");
21 }
22 //头插法
23 void link_init_tail(pNode *phead, int size) //传的是地址
24 {
25     pNode pNew = NULL;
26     pNode pTail = NULL;
27 
28     while( size > 0)
29     {
30         //申请内存
31         pNew = (pNode)malloc(sizeof(Node)); //注意这里为何不用pNode而用Node,因为sizeof(pNode) = 4
32         //赋值
33         pNew->Nnum_ = rand()%1000;
34         //插入链表
35         if(*phead == NULL) //链表为空时
36         {
37             *phead = pNew;//连接新的结点
38             pTail = pNew;
39         }
40         else//不为空
41         {
42             pTail->Nnext_ = pNew ; //连接新的结点
43              pTail = pNew; //改名字
44         }        
45         size --;
46     }
47 }
48 
49 int delete_special_pos(pNode *phead) //为了验证结果而将其打印出来,我们采用带有头指针的链表
50 {
51     if(*phead == NULL && (*phead)->Nnext_ == NULL)
52         return 0;
53     int i = 1;//为了叙述方便,我们假设其位置是3
54 
55     pNode pCur = *phead;
56     while( i < 3) //使pCur指向第三个结点
57     {
58         pCur = pCur->Nnext_;
59         i ++;
60     }
61     //删除第三个结点的int值
62     pNode pNext = pCur->Nnext_; //建立初始值
63     //我们要把pNext所指向结点int值放到pCur中,然后再删除pNext。此刻就完成了“狸猫换太子”
64     pCur->Nnext_ = pNext->Nnext_; 
65     pCur->Nnum_ = pNext->Nnum_;
66     free(pNext);
67     pNext = NULL; //防止野指针的出现
68     return 1;
69 }    
70 
71 int main(int argc, char const *argv[])
72 {
73     srand(time(NULL));
74     pNode phead = NULL;
75     link_init_tail(&phead, 10);
76     link_print(phead);    
77 
78     printf("ret:%d\n",delete_special_pos(&phead) );
79     link_print(phead);
80 
81     return 0;
82 }
View Code

二:编码实现环状单向链表(尾指针直接指向头指针,中间没有空结点),去除连续的重复元素的操作。(2012,人人)

比如:1(头)->2 ->2 ->3 ->3 ->1 ->1(头),去除以后的结果是 1 ->2 ->3(注意头部的 1 也要去掉一个); 

思路:

1、如果该链表为空或者长度为1,则直接返回。
2、遍历一次循环单向链表,删除连续的重复的结点;
3、判断最后一个结点是否和第一个结点值相同:
一)若相同,删除最后一个结点,并且返回头结点;
二)若不相同,直接返回头结点。

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <time.h>
  5 #include <assert.h>
  6 
  7 typedef struct tag
  8 {
  9     int Nnum_;
 10     struct tag *Nnext_;
 11 }Node, *pNode;
 12 
 13 
 14 void link_print(pNode phead, int size)
 15 {
 16     int i= 1;
 17     while(phead != NULL)
 18     {
 19         printf("%2d", phead->Nnum_);
 20         phead = phead->Nnext_;
 21         if( ++i > size)
 22             break;
 23     }
 24     printf("\n");
 25 }
 26 //尾插法
 27 void link_init_tail(pNode *phead, int size) //传的是地址
 28 {
 29     pNode pNew = NULL;
 30     pNode pTail = NULL;
 31 
 32     while( size > 0)
 33     {
 34         //申请内存
 35         pNew = (pNode)malloc(sizeof(Node)); //注意这里为何不用pNode而用Node,因为sizeof(pNode) = 4
 36         //赋值
 37         //pNew->Nnum_ = rand()%5;
 38         pNew->Nnum_ = 1; 
 39 
 40         //插入链表
 41         if(*phead == NULL) //链表为空时
 42         {
 43             *phead = pNew;//连接新的结点
 44             pTail = pNew;
 45         }
 46         else//不为空
 47         {
 48             pTail->Nnext_ = pNew ; //连接新的结点
 49              pTail = pNew; //改名字
 50         }    
 51         size --;
 52     }
 53     //生成一个首尾相连的环
 54     pTail->Nnext_ = *phead;
 55 }
 56 
 57 pNode unique( pNode phead)
 58 {
 59     //如果该链表为空或者长度为1,则直接返回。
 60     if( phead == NULL || phead->Nnext_ ==NULL)
 61         return phead;
 62 
 63     //遍历一次循环单向链表,
 64     pNode pCur = phead;
 65     pNode pNext = pCur->Nnext_;
 66 
 67     while(pNext != phead) 
 68     {
 69         //删除连续的重复的结点
 70         while(pCur->Nnum_ == pNext->Nnum_ && pNext != phead) 
 71         {
 72             pCur->Nnext_ = pNext->Nnext_;
 73             free(pNext);
 74             pNext= pCur->Nnext_;
 75         }
 76 
 77         if( pNext == phead) //判断最后一个结点是否和第一个结点值相同
 78             break;
 79         //int值不相等-->向后移动
 80         pCur = pNext;
 81         pNext = pNext->Nnext_;
 82     }
 83     
 84     if( pCur->Nnum_ == pNext->Nnum_)
 85     {
 86     //所有值域全部相同
 87         if(pNext == pCur) 
 88         {
 89             printf("All the link's elements are equal\n");
 90             printf("the value is:%d\n",pNext->Nnum_);
 91             //free(pNext);// 为什么加上这两句就错了?
 92             //pNext = NULL;
 93             return pCur;
 94         }
 95     //存在值域不相同的结点->此时剩余的结点组成一个循环链表
 96         pCur->Nnext_ = pNext->Nnext_;
 97         free(pNext);
 98         return pCur;
 99     }
100     //不相等,这时pNext == *phead
101     return pNext;
102 }
103 
104 int main(int argc, char const *argv[])
105 {
106     srand(time(NULL));
107     pNode phead = NULL;
108     link_init_tail(&phead, 10); //10为初始链表的长度
109     link_print(phead,15); 
110 
111     pNode pRet = unique(phead);
112 
113     link_print(pRet, 10);
114     return 0;
115 }
View Code

链表的快慢指针的使用,详见下篇:链表三——快慢指针的使用

posted @ 2014-11-10 22:22  Stephen_Hsu  阅读(360)  评论(0编辑  收藏  举报