51. 实现对 有头单链表 的基本操作 包括创建,插入,查找,删除,求长,销毁,正逆遍历,逆置,排序...

 

 

1 #include <stdio.h>
2 #include <stdlib.h>
3 typedef struct node
4 {
5     int data;
6     struct node *next;
7 }Node;

 

//创建一个带头结点的空链表
int createList(Node ** head)
{
    *head = (Node*)malloc(sizeof(Node));
    if(*head == NULL)
    {
        return -1;
    }
    else
    {
        (*head)->next = NULL;
        return 0;
    }
}

 

 1 //尾插1 //找前驱节点方式
 2 void insertList_end(Node *head,int data)
 3 {
 4     Node* newNode = (Node*)malloc(sizeof(Node));
 5     newNode->data = data;
 6 
 7 
 8     while(head->next)
 9     {
10         head = head->next;
11     }
12 
13     head->next = newNode;
14     newNode->next = NULL;
15 }

 

 

 1 //尾插2 
 2 //找待插入的空间地址,也就是前驱节点的next成员所在的内存空间
 3 //这种方式更适合操作无头节点的链表
 4 void insertList_end(Node *head, int data)
 5 {
 6     Node* newNode = (Node*)malloc(sizeof(Node));
 7     newNode->data = data;
 8     newNode->next = NULL;
 9 
10     Node** p = &(head->next);//最符合逻辑的初始化写法
11    // Node** p = &head;
12     while(*p)//遍历到待插入的地址结束。
13     {
14         p = &((*p)->next);
15     }
16     *p = newNode;
17 }

 

 

 

1 //头插1
2 void insertList_head(Node *head,int data)
3 {
4     Node* newNode = (Node*)malloc(sizeof(Node));
5     newNode->data = data;
6 
7     newNode->next = head->next;
8     head->next = newNode;
9 }

 

 1 //头插2 //这个方式用在有头链表头插上就有点脱裤子放屁了。但还是写一写好了
 2 //这个方式适合用于无头链表的头插
 3 void insertList_head(Node *head, int data)
 4 {
 5     Node* newNode = (Node*)malloc(sizeof(Node));
 6     newNode->data = data;
 7 
 8     Node **p = &(head->next);
 9     newNode->next = (*p);
10     *p = newNode;
11 }

 

 1 //查找1
 2 //功能:返回待查找节点的地址,不存在返回NULL
 3 Node* searchList(Node *head,int findData)
 4 {
 5 #if 1
 6     head = head->next;
 7     while(head)
 8     {
 9         if(head->data == findData)
10         {
11             return head;
12         }
13         head = head->next;
14     }
15     return NULL;
16 #endif
17 
18 #if 0//只是做了点优化
19     head = head->next;
20     while(head)
21     {
22         if(head->data == findData)
23         {
24             break;
25         }
26         head = head->next;
27     }
28     return head;//因为没找到head会==NULL时结束循环,找到会跳出循环,所以上面两个return可以合为一个
29 
30 #endif
31 }
32 
33 
34 
35 
36 
37 
38 
39 //删除1 //遍历到前驱节点
40 //功能:已有待删除节点的地址,实现删除此节点的操作
41 void deleteNodeList1(Node* head,Node *deleteNode)
42 {
43     while(head->next != deleteNode)//遍历到前驱节点
44     {
45         head = head->next;
46     }
47     head->next = deleteNode->next;
48     free(deleteNode);
49 }
50 
51 
52 //删除1.1 //对删除1的优化版,无需遍历。
53 //功能:已有待删除节点的地址,实现删除此节点的操作,优化版
54 //优化的原理是后驱节点的所有数据覆盖拷贝到待删除节点,再删除后驱节点。不需再遍历
55 //但是特殊情况是如果待删除节点为尾节点并没有后驱节点,所以需要分两种情况。
56 void deleteNodeList2(Node* head,Node *deleteNode)
57 {
58     Node* postNode = deleteNode->next;
59     if(postNode)
60     {
61         deleteNode->data = postNode->data;
62         deleteNode->next = postNode->next;
63         free(postNode);
64     }
65     else
66     {
67         while(head->next != deleteNode)//遍历到前驱节点
68         {
69             head = head->next;
70         }
71         head->next = deleteNode->next;
72         free(deleteNode);
73     }
74 
75 }

 

 

 1 //查找2
 2 //功能:返回待查找节点的前驱节点的地址。方便后来的操作
 3 //注意点,如果不存在待查找节点,那更不存在前驱节点了,直接返回NULL
 4 //另外,此方式只适合有头链表,不适合无头链表,因为如果无头链表第一个有效节点没前驱节点。
 5 Node* searchListPre(Node *head,int findData)
 6 {
 7    while(head->next)
 8    {
 9        if(head->next->data == findData)
10        {
11            return head;
12        }
13        head = head->next;
14    }
15    return NULL;
16 }
17 
18 
19 //删除2
20 //功能:已有待删除节点的前驱节点的地址,实现删除此待删节点的操作
21 //需配合返回前驱节点的查找函数
22 //只适合有头链表
23 void deleteNodeList3(Node *deleteNodePre)
24 {
25     Node* deleteNode = deleteNodePre->next;
26     deleteNodePre->next = deleteNode->next;
27     free(deleteNode);
28 
29 }

 

 

 1 //查找3
 2 //返回待查找节点的所在的挂载空间的地址,(挂载空间里存储的"待查找节点的首地址")(挂载空间也就是前驱节点的next成员所在的空间),如果不存在此节点,返回NULL
 3 Node** searchList(Node *head,int findData)
 4 {
 5     Node **p = &(head->next);
 6     while(*p)
 7     {
 8         if((*p)->data == findData)
 9             return p;
10 
11         p = &((*p)->next);
12     }
13     return NULL;
14 }
15 
16 //删除3
17 void deleteNodeList(Node **deleteNode)
18 {
19     Node* temp = *deleteNode;
20     *deleteNode = (*deleteNode)->next;
21     free(temp);
22 }



 1 //逆置链表
 2 //方法为拆分为两个链表,一个包含头结点的空链表A,一个是不带头结点的链表B。,
 3 //从链表B里从头到尾取节点,用头插法将节点依次插入到链表A中。
 4 void reverseList(Node * head)
 5 {
 6     //无头链表B
 7     Node* headB = head->next;
 8 
 9     //有头空链表A
10     head->next = NULL;
11     Node* headA = head;
12 
13     while(headB)
14     {
15         Node* newNode = headB;
16         headB = headB->next;
17         newNode->next = headA->next;
18         headA->next = newNode;
19     }
20 }

 

 

 1 //求链表长度
 2 int getLenList(Node* head)
 3 {
 4     head = head->next;
 5     int len = 0;
 6     while(head)
 7     {
 8         len++;
 9         head= head->next;
10     }
11     return len;
12 }

 

 

 1 //清空链表 留头节点释放删除掉所有有效节点,只留头结点
 2 void clearList(Node* head)
 3 {
 4     Node* temp = head->next;
 5     head->next = NULL;
 6 
 7     while(temp)
 8     {
 9         Node* p = temp;
10       //  free(p);
11         temp = temp->next;
12         free(p);
13     }
14 }

 

 

 1 //销毁链表 释放删除掉所有节点,包括头结点
 2 //头结点被销毁后,调用函数中头指针应该置为NULL,相当于修改了其指向,因此需要使用二级指针参数。
 3 void destroyList(Node** head)
 4 {
 5     while(*head)//循环结束会为NULL
 6     {
 7         Node* temp = *head;
 8         *head = (*head)->next;
 9 
10         free(temp);
11     }
12 }

 

 

 1 //销毁链表 释放删除掉所有节点,包括头结点
 2 //头结点被销毁后,调用函数中头指针应该置为NULL,相当于修改了其指向,因此需要使用二级指针参数。
 3 void destroyList(Node** head)
 4 {
 5     while(*head)//循环结束会为NULL
 6     {
 7         Node* temp = *head;
 8         *head = (*head)->next;
 9 
10         free(temp);
11     }
12 }

 

 

 

  1 //对链表排序,使用选择排序
  2 /*-------------------使用选择排序--------------------*/
  3 //对数据域进行交换1   套用选择排序模板
  4 void selectSortDataUp(Node* head)//升序
  5 {
  6     int i,j;
  7     int len = getLenList(head);
  8    // printf("len = %d\n",len);
  9     Node* cur = head;
 10     Node* post = NULL;
 11 
 12 
 13     for(i = 0;i<len-1;i++)
 14     {
 15         cur = cur->next;
 16         post = cur->next;
 17         for(j = i+1;j<len;j++)
 18         {
 19             if(cur->data > post->data)
 20             {
 21 #if 0
 22                 Node temp;
 23                 temp.data = cur->data;
 24                 cur->data = post->data;
 25                 post->data = temp.data;
 26 #endif
 27 #if 1
 28                 int temp;
 29                 temp = cur->data;
 30                 cur->data = post->data;
 31                 post->data = temp;
 32 #endif
 33 
 34             }
 35             post = post->next;
 36         }
 37     }
 38 }
 39 
 40 //对数据域进行交换2  判NULL方式
 41 void selectSortDataDown(Node* head)//降序
 42 {
 43     Node *Nodei,*Nodej;
 44     for(Nodei = head->next ; Nodei->next ; Nodei = Nodei->next)
 45     {
 46         for(Nodej = Nodei->next; Nodej ;Nodej = Nodej->next)
 47         {
 48             if(Nodei->data < Nodej->data)
 49             {
 50                 int temp = Nodei->data;
 51                 Nodei->data = Nodej->data;
 52                 Nodej->data = temp;
 53             }
 54         }
 55     }
 56 }
 57 
 58 
 59 //对数据域进行交换2.1 选择排序的优化,比而不换,只记下标,比完再换。
 60 void selectSortDataDown2(Node* head)//降序
 61 {
 62     Node *Nodei,*Nodej;
 63     Node *idx;
 64     for(Nodei = head->next ; Nodei->next ; Nodei = Nodei->next)
 65     {
 66         idx = Nodei;
 67         for(Nodej = Nodei->next; Nodej ;Nodej = Nodej->next)
 68         {
 69             if(idx->data < Nodej->data)
 70             {
 71                  idx = Nodej;
 72             }
 73         }
 74         if(idx != Nodei)
 75         {
 76             Nodei->data ^= idx->data;
 77             idx->data ^= Nodei->data;
 78             Nodei->data ^= idx->data;
 79         }
 80 
 81     }
 82 }
 83 
 84 
 85 //对指针域进行交换,调整节点在链表结构中的挂载顺序
 86 //i,j,iPre,jPre,都是指向一个节点的,打断重连时并没有改其指向,所以重连后,这四个指针仍旧指向原先的节点。
 87 //始终保持让i指向左位置,j指向右位置
 88 void selectSortPointer(Node* head)//升序
 89 {
 90     Node* i;
 91     Node* j;
 92     Node* iPre;
 93     Node* jPre;
 94     for(iPre = head,i = head->next;i->next;iPre = iPre->next,i = iPre->next)
 95     {
 96         for(jPre = i,j = jPre->next;j;jPre = jPre->next,j = jPre->next)
 97         {
 98             if(i->data > j->data)
 99             {
100                 if(jPre == i)
101                 {
102                     iPre->next = j;
103                     Node* temp = j->next;
104                     j->next = i;
105                     i->next = temp;
106 
107                     i = iPre->next;
108                     jPre = i;
109                 }
110                 else
111                 {
112                     iPre->next = j;
113                     Node* temp = j->next;
114                     j->next = i->next;
115                     jPre->next = i;
116                     i->next = temp;
117 
118                     i = iPre->next;
119                 }
120             }
121         }
122     }
123 }

 

 

 1 //对链表排序,使用选择排序
 2 //对数据域进行交换1     套用冒泡排序模板
 3 void bubbleSortDataUp(Node* head)//升序
 4 {
 5     int i,j;
 6     int len = getLenList(head);
 7     Node* cur = NULL;
 8     for(i = 0;i<len-1;i++)
 9     {
10         cur = head->next;
11         for(j=0;j<len-1-i;j++)
12         {
13             if(cur->data > cur->next->data)
14             {
15                 cur->data ^= cur->next->data;
16                 cur->next->data ^= cur->data;
17                 cur->data ^= cur->next->data;
18             }
19             cur = cur->next;
20         }
21     }
22 }
23 
24 
25 //对数据域进行交换1.1 优化版,已序而不排
26 void bubbleSortDataUp2(Node* head)
27 {
28     int i,j;
29     int len = getLenList(head);
30     Node* cur = NULL;
31     int doswap;//
32     for(i = 0;i<len-1;i++)
33     {
34         doswap = 0;//
35         cur = head->next;
36         for(j=0;j<len-1-i;j++)
37         {
38             if(cur->data > cur->next->data)
39             {
40                 doswap = 1;//
41 
42                 cur->data ^= cur->next->data;
43                 cur->next->data ^= cur->data;
44                 cur->data ^= cur->next->data;
45 
46             }
47             cur = cur->next;
48         }
49         if(doswap == 0)//
50             break;
51     }
52 }
53 
54 //对数据域进行交换2   判NULL方式没法实现
55 
56 
57 
58 //对指针域排序
59 void bubbleSortPointer(Node* head)//升序
60 {
61     int len = getLenList(head);
62     int m,n;
63     Node *i = head->next;
64     Node *j = i->next;
65     Node *iPre = head;
66     for(m = 0;m<len-1;m++)
67     {
68         for(n = 0;n<len-1-m;n++)
69         {
70             if(i->data > j->data)
71             {
72                 iPre->next = j;
73                 Node* temp = j->next;
74                 j->next = i;
75                 i->next = temp;
76 
77                 i = iPre->next;
78                 j = i->next;
79             }
80 
81             iPre = iPre->next;
82             i = iPre->next;
83             j = i->next;
84         }
85 
86         iPre = head;
87         i = iPre->next;
88         j = i->next;
89     }
90 }

 

 

 

 1 //正序打印链表
 2 void traverseList(Node* head)
 3 {
 4     head = head->next;
 5     while(head)
 6     {
 7         printf("%d ",head->data);
 8         head = head->next;
 9     }
10 }
11 
12 
13 
14 //逆序打印链表
15 void traverseList2(Node* head)
16 {
17     if(head->next == NULL)
18     {
19         return;
20     }
21     else
22     {
23         head = head->next;
24         traverseList2(head);
25         printf("%d ",head->data);
26     }
27 }

 

 

 

 

  1 int main(void) //测试,均通过QT测试通过。
  2 {
  3     Node * listhead;
  4     int res = createList(&listhead);
  5     if(res == 0)
  6     {
  7         printf("create succeed\n");
  8     }
  9     else
 10     {
 11         printf("create error\n");
 12         exit(-1);
 13     }
 14     int i;
 15     for(i = 0; i<5;i++)
 16     {
 17       //  insertList_end(listhead,i);
 18         insertList_head(listhead,i);
 19     }
 20 
 21     traverseList(listhead);putchar(10);
 22 
 23 #if 0
 24     Node* findNode = searchList(listhead,3);
 25     if(findNode)
 26         printf("%d\n",findNode->data);
 27     else
 28         printf("There is no such node\n");
 29 #endif
 30 #if 0
 31     Node* findNodePre = searchListPre(listhead,3);
 32     Node* findNode = findNodePre->next;
 33     if(findNode)
 34         printf("%d\n",findNode->data);
 35     else
 36         printf("There is no such node\n");
 37 #endif
 38 
 39 #if 0
 40     Node** findNode = searchList(listhead,3);
 41     if(findNode)
 42         printf("%d\n",(*findNode)->data);
 43     else
 44         printf("There is no such node\n");
 45 #endif
 46 #if 0
 47     Node* findNode = searchList(listhead,3);
 48     if(findNode)
 49         deleteNodeList2(listhead,findNode);
 50     traverseList(listhead);putchar(10);
 51 #endif
 52 
 53 #if 0
 54     Node* findNodePre = searchListPre(listhead,3);
 55     if(findNodePre)
 56         deleteNodeList3(findNodePre);
 57     traverseList(listhead);putchar(10);
 58 #endif
 59 
 60 #if 0
 61     Node** findNode = searchList(listhead,3);
 62     if(findNode)
 63         deleteNodeList(findNode);
 64     traverseList(listhead);putchar(10);
 65 
 66 #endif
 67 
 68 #if 0
 69     reverseList(listhead);
 70     traverseList(listhead);putchar(10);
 71 #endif
 72 
 73 #if 0
 74     printf("len = %d\n",getLenList(listhead));
 75 #endif
 76 
 77 #if 0
 78     clearList(listhead);
 79 //    traverseList(listhead);putchar(10);
 80     for(i = 7; i<15;i++)
 81     {
 82         insertList_end(listhead,i);
 83       //  insertList_head(listhead,i);
 84     }
 85     traverseList(listhead);putchar(10);
 86 
 87 #endif
 88 
 89 #if 0
 90     destroyList(&listhead);
 91     printf("listhead = %d",listhead);
 92 
 93 #endif
 94 
 95 #if 0
 96     traverseList2(listhead);putchar(10);
 97 #endif
 98 
 99 #if 0
100 
101   //  selectSortDataUp(listhead);
102  //   selectSortDataDown(listhead);
103     selectSortDataDown2(listhead);
104     traverseList(listhead);putchar(10);
105 
106 #endif
107 
108 #if 0
109     bubbleSortDataUp2(listhead);
110     traverseList(listhead);putchar(10);
111 #endif
112 
113 #if 0
114     selectSortPointer(listhead);
115     traverseList(listhead);putchar(10);
116 
117 #endif
118 #if 1
119     bubbleSortPointer(listhead);
120     traverseList(listhead);putchar(10);
121 
122 #endif
123 
124 
125     return 0;
126 }

 

转载于:https://www.cnblogs.com/ZhuLuoJiGongYuan/p/9531717.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值