基数计数排序+单链表
计数排序
基数排序
单链表
计数排序(时间复杂度,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 }

浙公网安备 33010602011771号