基数计数排序+单链表

计数排序

基数排序

单链表

 

 

计数排序(时间复杂度,O(N) )

 1 void countSort(int array[],int range ,int len)
 2 {
 3     //range是取值范围,假设0到10内,是11个下标,所以range+1
 4     vector<int>arr(range+1,0);
 5     for (int i = 0; i < len; i++)
 6     {
 7         arr[array[i]]++;
 8     }
 9     for (int i = 0,j = 0; i <range+1; i++)
10     {
11         while (arr[i]-- > 0)
12         {
13             array[j++] = i;
14         }
15     }
16 }

 

基数排序(时间复杂度,O(N) )后期补解析

 1 static int maxbits(int array[],int len)
 2 {
 3     int max = -1;
 4     for (int i = 0; i < len; i++)
 5     {
 6         max = max > array[i] ? max : array[i];
 7     }
 8     int res = 0;
 9     while (max != 0)
10     {
11         res++;
12         max /= 10;
13     }
14     return res;
15 }
16 
17 static int getDigit(int x, int d)
18 {
19     return ((x / ((int)pow(10, d - 1))) % 10);
20 }
21 
22 static void radixSort(int array[], int begin, int end, int digit)
23 {
24     int radix = 10;
25     int i = 0, j = 0;
26     vector<int>bucket(end - begin + 1);
27     for (int d = 1; d <= digit; d++)
28     {
29         vector<int>count(radix);
30         for (i = begin; i <= end; i++)
31         {
32             j = getDigit(array[i], d);
33             count[j]++;
34         }
35         for (i = 1; i < radix; i++)
36         {
37             count[i] = count[i] + count[i - 1];
38         }
39         for (i = end; i >= begin; i--)
40         {
41             j = getDigit(array[i], d);
42             bucket[count[j] - 1] = array[i];
43             count[j]--;
44         }
45         for (i = begin, j = 0; i <= end; i++, j++)
46         {
47             array[i] = bucket[j];
48         }
49     }
50 }
51 
52 void radixSort(int array[], int len)
53 {
54     if (array == NULL || len < 2)
55     {
56         return;
57     }
58     radixSort(array, 0, len - 1, maxbits(array,len));
59 }

 

 

 

单链表

基础创建,增加,删除

 1 typedef struct LNode {
 2     int data;
 3     LNode *next;
 4 }LNode,*LinkList;
 5 
 6 int ListInsert(LinkList &L, int i, int e)
 7 {
 8     LinkList p=L;
 9     int j = 0;
10     while(p&&j < e)
11     {
12         p = p->next;
13         j++;
14     }
15     if (!p || j > i - 1)
16     {
17         return -1;
18     }
19     LinkList s = (LinkList)malloc(sizeof(LNode));
20     s->data = e;
21     s->next = p->next;
22     p->next = s;
23     return 1;
24 }
25 
26 int ListDelete(LinkList &L, int i, int &e)
27 {
28     LinkList p = L;
29     int j = 0;
30     while (p&&j < i)
31     {
32         p = p->next;
33         j++;
34     }
35     if (!p || j > i - 1)
36     {
37         return -1;
38     }
39     LinkList q = p->next;
40     p->next = q->next;
41     e = q->data;
42     delete[] q;
43     return e;
44 }
45 //尾插法
46 void CreatList(LinkList &L, int n)
47 {
48     LinkList p,q;
49     L = (LinkList)malloc(sizeof(LNode));
50     L->next = NULL;
51     q = L;
52     for (int i = n; i > 0; i--)
53     {
54         p = (LinkList)malloc(sizeof(LNode));
55         cin >> p->data;
56         p->next = NULL;
57         q->next = p;
58         q = q->next;
59     }
60 }

 

单链表逆序

方法一: 

利用一个栈来完成逆序,先进后出原则。

先把链表每个值压入栈中,然后再出栈回填到链表中,完成逆序。

 1 void reserseList(LinkList &L)
 2 {
 3     LinkList p = L;
 4     stack<int>s;
 5     while (p->next != NULL)
 6     {
 7         p = p->next;
 8         s.push(p->data);
 9     }
10     p = L;
11     while (p->next != NULL)
12     {
13         p = p->next;
14         p->data = s.top();
15         s.pop();
16     }
17 }

 

方法二:

 不借助额外空间进行逆序

 1 LinkList reverseList(LinkList &L)
 2 {
 3     LinkList pre = NULL;
 4     LinkList next = NULL;
 5     LinkList p = L;
 6     while (p != NULL)
 7     {
 8         next = p->next;
 9         p->next = pre;
10         pre = p;
11         p = next;
12     }
13     return pre;
14 }

 

单链表回文数判断

方法一:

额外空间复杂度O(N) ,用栈来做

 1 bool isPalindrome(LinkList &L)
 2 {
 3     LinkList p = L;
 4     stack<int>s;
 5     while (p->next != NULL)
 6     {
 7         p = p->next;
 8         s.push(p->data);
 9     }
10     p = L;
11     while (p->next != NULL)
12     {
13         p = p->next;
14         if (p->data != s.top())
15         {
16             return false;
17         }
18         s.pop();
19     }
20     return true;
21 }

 

方法二:

优化方法一,额外空间复杂度O(N/2),也是用栈实现的。

主要思想是,用快慢指针法,p是一次走两步,right一次走一步,p先到末尾,right这个时候在中间的位置

在跳指针的时候,就用栈来存储从第一个结点到中间结点的值,然后再出栈跟中间结点到末尾结点之间的值来做比较

 1 bool isPalindrome2(LinkList L)
 2 {
 3     if (L == NULL || L->next == NULL)
 4     {
 5         return true;
 6     }
 7     LinkList right = L->next;
 8     LinkList p = L->next;
 9     stack<int>s;
10     while (p->next != NULL && p->next->next != NULL)
11     {
12         s.push(right->data);
13         right = right->next;
14         p = p->next->next;
15     }
16     while (!s.empty())
17     {
18         right = right->next;
19         if (right->data != s.top())
20         {
21             return false;
22         }
23         s.pop();
24     }
25     return true;
26 }

 

 方法三:

不使用额外空间来进行的操作,额外空间复杂度O(1)

主要思想,使用快排指针进行操作,将整段链表看成3个部分,begin  Mid  end

定义两个链表的指针,慢指针n1步长为1,快指针n2步长为2。当n2到达尾部的时候,n1同时到达中部。

接着将中部到尾部的链表逆序,逆序完成之后,n1变成了尾部的结点,n2变成了首部的结点。

然后一个从前往后,一个从后往前,进行比较。

 1 bool isPalindrome3(LinkList L)
 2 {
 3     if (L == NULL || L->next == NULL)
 4     {
 5         return true;
 6     }
 7     LinkList n1 = L->next;
 8     LinkList n2 = L->next;
 9     while (n2->next != NULL && n2->next->next != NULL)
10     {
11         n1 = n1->next;//n1 变成 mid
12         n2 = n2->next->next;//n2 变成 end
13     }
14     n2 = n1->next;//n2变成右边第一个结点
15     n1->next = NULL;//mid->next = NULL
16     LinkList n3 = NULL;
17     
18     while (n2 != NULL)//将右边反转
19     {
20         n3 = n2->next;
21         n2->next = n1;
22         n1 = n2;
23         n2 = n3;
24     }//n2=NULL,n1 = 最后一个位置,n3=NULL
25     n3 = n1;//保存最后一个结点
26     n2 = L->next;//n2等于首节点
27     bool res = true;
28     while (n1 != NULL && n2 != NULL)
29     {
30         if (n1->data != n2->data)
31         {
32             res = false;
33             break;
34         }
35         n1 = n1->next;//R->mid
36         n2 = n2->next;//L->mid
37     }
38     n1 = n3->next;
39     n3->next = NULL;
40     while (n1 != NULL)
41     {
42         n2 = n1->next;
43         n1->next = n3;
44         n3 = n1;
45         n1 = n2;
46     }
47     return res;
48 }

 

单链表类似于荷兰国旗问题

【题目】给定一个单链表的头节点head,节点的值类型是整型,再给定一个整 数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于pivot的 节点,中间部分都是值等于pivot的节点,右部分都是值大于pivot的节点。 

方法一:

额外空间复杂度O(N)。

主要思想:

用一个容器vector来装单链表每个结点的值。

然后对vector进行partition,最后把vector容器中的值给单链表中替换掉

 1 void listPartition(LinkList &L)
 2 {
 3     LinkList p = L->next;
 4     vector<int>array;
 5     while (p != NULL)
 6     {
 7         array.push_back(p->data);
 8         p = p->next;
 9     }
10     //判断小于等于大于5
11     arrPartition(array, 5);
12     p = L->next;
13     int i = 0;
14     while (p != NULL)
15     {
16         p->data = array[i++];
17         p = p->next;
18     }
19 }
20 void arrPartition(vector<int>&array, int pivot)
21 {
22     int small = -1;
23     int big = array.size();
24     int index = 0;
25     while (index != big)
26     {
27         if (array[index] < pivot)
28         {
29             Swap(array, ++small, index++);
30         }
31         else if (array[index] == pivot)
32         {
33             index++;
34         }
35         else {
36             Swap(array, --big, index);
37         }
38     }
39 }
40 void Swap(vector<int>&array, int i, int j)
41 {
42     int temp = array[i];
43     array[i] = array[j];
44     array[j] = temp;
45 }

 

方法二:

额外空间复杂度O(1)

定义6个额外空间变量,H代表头,T代表尾,s,e,b 分别对应小于部分,等于部分,大于部分,例如sT小于部分头结点

再定义一个next变量,用来指向下一个结点

首先全部置为空,p指针指向这个链表第一个位置

然后分别3个if语句的判断,看这个p的值是小于这个设定的pivot还是等于或者大于这个pivot

以小于为例,如果小于这个pivot,那么开始判断,这个小于部分是否为空,如果为空,说明这个p的值是第一个小于部分的值

如果不为空,说明小于部分已经有值了,那么就进行尾插操作,尾插到上一个小于部分结点的后面。

等于和大于的操作跟小于的一样,就是结点不同。

当以上操作都执行完了之后,再来开始边界考虑

先来看小于区域存不存在,如果存在,就把小于区域的尾部跟跟等于区域的头部连接起来。

然后再来判断等于部分有没有值,如果有值就不变,如果没值就把等于区域的尾结点跟小于区域的尾结点连接起来

最后来连接大于区域,先判断等于区域是否存在,如果存在就直接把等于区域的尾结点指向大于区域头结点。

函数末尾返回值,判断小于区域是否存在,如果存在就返回小于区域头结点。如果不存在就看等于区域存不存在,等于区域存在就返回等于区域头结点,如果等于区域也不存在就直接返回大于区域头结点

 1 LinkList listPartition2(LinkList &L, int pivot)
 2 {
 3     LinkList sH = NULL;
 4     LinkList sT = NULL;
 5     LinkList eH = NULL;
 6     LinkList eT = NULL;
 7     LinkList bH = NULL;
 8     LinkList bT = NULL;
 9     LinkList next = NULL;
10     LinkList p = L->next;
11     while (p != NULL)
12     {
13         next = p->next;
14         p->next = NULL;
15         if (p->data < pivot)
16         {
17             if (sH == NULL)
18             {
19                 sH = p;
20                 sT = p;
21             }
22             else {
23                 sT->next = p;
24                 sT = p;
25             }
26         }
27         else if (p->data == pivot)
28         {
29             if (eH == NULL)
30             {
31                 eH = p;
32                 eT = p;
33             }
34             else {
35                 eT->next = p;
36                 eT = p;
37             }
38         }
39         else if (p->data > pivot)
40         {
41             if (bH == NULL)
42             {
43                 bH = p;
44                 bT = p;
45             }
46             else {
47                 bT->next = p;
48                 bT = p;
49             }
50         }
51         p = next;
52     }
53     if (sT != NULL)
54     {
55         sT->next = eH;
56         eT = eT == NULL ? sT : eT;
57     }
58     if (eT != NULL)
59     {
60         eT->next = bH;
61     }
62     return sH != NULL ? sH : eH != NULL ? eH : bH;
63 }

posted @ 2020-08-02 21:23  袁君(Louis)  阅读(154)  评论(0)    收藏  举报