一、利用字符重複出現的次數,編寫一個方法,實現基本的字符串壓縮功能。數據結構
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<conio.h> 4 #include <string.h> 5 6 /* 7 重複字符壓縮 8 */ 9 void RepeatCharReduce(char *str, int n, char *s){ 10 11 // char s[20]; 12 char tmp = str[0]; 13 s[0] = tmp; 14 int j = 1; 15 int count = 1; 16 for(int i = 1; i <n; i++){ 17 if(str[i] == tmp){ 18 count++; 19 } 20 else{ 21 s[j] = count; 22 j++; 23 tmp = str[i]; 24 s[j] = str[i]; 25 count = 1; 26 j++; 27 } 28 } 29 s[j] = count; 30 31 } 32 33 int main(){ 34 char str[] = "aabcccccaaa"; 35 char s[20] = "0"; 36 RepeatCharReduce(str, 11, s); 37 for(int j = 0; j < 11; j++){ 38 printf("%c", str[j]); 39 } 40 printf("\n"); 41 for(int i = 0; i < 11; i += 2){ 42 printf("%c%d", s[i], s[i+1]); 43 } 44 printf("\n"); 45 getch(); 46 return 0; 47 }
二、給定一個字符串,要求把字符串前面的若干個字符移動到字符串的尾部,如把字符串「abcdef」前面的2個字符'a'和'b'移動到字符串的尾部,使得原字符串變成字符串「cdefab」。請寫一個函數完成此功能,要求對長度爲n的字符串操做的時間複雜度爲 O(n),空間複雜度爲 O(1)。ide
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<conio.h> 4 #include<math.h> 5 #include<time.h> 6 #include <string.h> 7 8 void ReverseString(char *s, int from, int to) 9 { 10 while(from < to){ 11 char t = s[from]; 12 s[from++] = s[to]; 13 s[to--] = t; 14 } 15 } 16 17 void LeftRotateString(char *s, int n, int m) 18 { 19 m %= n; 20 ReverseString(s, 0, m-1); 21 ReverseString(s, m, n-1); 22 ReverseString(s, 0, n-1); 23 } 24 25 int main(){ 26 char s[] = "abcdefgh"; 27 for(int i = 0; i < 8; i++){ 28 printf("%c ", s[i]); 29 } 30 printf("\n"); 31 LeftRotateString(s, 8, 3); 32 for(int i = 0; i < 8; i++){ 33 printf("%c ", s[i]); 34 } 35 printf("\n"); 36 getch(); 37 return 0; 38 }
三、鏈表翻轉。給出一個鏈表和一個數k,好比,鏈表爲1→2→3→4→5→6,k=2,則翻轉後2→1→6→5→4→3,若k=3,翻轉後3→2→1→6→5→4,若k=4,翻轉後4→3→2→1→6→5,用程序實現。函數
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<conio.h> 4 #include<math.h> 5 #include<time.h> 6 #include <string.h> 7 8 #define OK 1 9 #define ERROR 0 10 #define TRUE 1 11 #define FALSE 0 12 13 #define MAXSIZE 20 /* 存儲空間初始分配量 */ 14 15 typedef int Status;/* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */ 16 typedef int ElemType;/* ElemType類型根據實際狀況而定,這裏假設爲int */ 17 18 typedef struct Node{ 19 int data; 20 struct Node *next; 21 }Node, *LinkList; 22 23 /* 初始化順序線性表 */ 24 Status InitList(LinkList *L) 25 { 26 *L=(LinkList)malloc(sizeof(Node)); /* 產生頭結點,並使L指向此頭結點 */ 27 if(!(*L)) /* 存儲分配失敗 */ 28 { 29 return ERROR; 30 } 31 (*L)->next=NULL; /* 指針域爲空 */ 32 return OK; 33 } 34 35 36 /* 隨機產生n個元素的值,創建帶表頭結點的單鏈線性表L(頭插法) */ 37 void CreateListHead(LinkList *L, int n) 38 { 39 LinkList p; 40 int i; 41 srand(time(0)); /* 初始化隨機數種子 */ 42 *L = (LinkList)malloc(sizeof(Node)); 43 (*L)->next = NULL; /* 先創建一個帶頭結點的單鏈表 */ 44 for (i=0; i < n; i++) 45 { 46 p = (LinkList)malloc(sizeof(Node)); /* 生成新結點 */ 47 p->data = rand()%100+1; /* 隨機生成100之內的數字 */ 48 printf("%d ", p->data); 49 p->next = (*L)->next; 50 (*L)->next = p; /* 插入到表頭 */ 51 } 52 } 53 /* 初始條件:順序線性表L已存在。操做結果:返回L中數據元素個數 */ 54 int ListLength(LinkList L) 55 { 56 int i=0; 57 LinkList p=L->next; /* p指向第一個結點 */ 58 while(p) 59 { 60 i++; 61 p=p->next; 62 } 63 return i; 64 } 65 Status visit(ElemType c) 66 { 67 printf("-> %d ",c); 68 return OK; 69 } 70 /* 初始條件:順序線性表L已存在 */ 71 /* 操做結果:依次對L的每一個數據元素輸出 */ 72 Status ListTraverse(LinkList L) 73 { 74 LinkList p=L->next; 75 while(p) 76 { 77 visit(p->data); 78 p=p->next; 79 } 80 printf("\n"); 81 return OK; 82 } 83 84 LinkList ListReverse2(LinkList L) 85 { 86 LinkList current, p; 87 if (L == NULL) 88 { 89 return NULL; 90 } 91 current = L->next; 92 while (current->next != NULL) 93 { 94 p = current->next; 95 current->next = p->next; 96 p->next = L->next; 97 L->next = p; 98 } 99 ListTraverse(L); 100 return L; 101 } 102 /* 103 一、鏈表翻轉。給出一個鏈表和一個數k, 104 好比,鏈表爲1→2→3→4→5→6,k=2,則翻轉後2→1→6→5→4→3, 105 若k=3,翻轉後3→2→1→6→5→4, 106 若k=4,翻轉後4→3→2→1→6→5,用程序實現。 107 108 對於鏈表而言只是對指針的指向調換,因此不會耗費額外存儲空間,空間複雜度O(1) 109 時間複雜度此處看來也是線性的 110 */ 111 112 LinkList ReverseSpecArea(LinkList L, int k){ 113 LinkList current, p, q; 114 LinkList temp; 115 int i = 1; 116 if (L == NULL) 117 { 118 return NULL; 119 } 120 current = L->next; 121 122 while (current->next != NULL) 123 { 124 p = current->next; 125 current->next = p->next; 126 p->next = L->next; 127 L->next = p; 128 if(++i >= k){ 129 break; 130 } 131 }//current始終指向起先除去頭結點的第一個元素 132 temp = current; 133 current = current->next; 134 while(current->next != NULL){ 135 p = current->next; 136 current->next = p->next; 137 p->next = temp->next; 138 temp->next = p; 139 } 140 ListTraverse(L); 141 142 return L; 143 } 144 145 146 void ReverseString(char *s, int from, int to) 147 { 148 while(from < to){ 149 char t = s[from]; 150 s[from++] = s[to]; 151 s[to--] = t; 152 } 153 } 154 155 void LeftRotateString(char *s, int n, int k) 156 { 157 k %= n; 158 ReverseString(s, 0, k-1); 159 ReverseString(s, k, n-1); 160 } 161 162 int main(){ 163 LinkList L; 164 LinkList h; 165 Status i; 166 int j,k,pos,value; 167 int length; 168 char opp; 169 ElemType e; 170 i=InitList(&L); 171 printf("%d\n", i); 172 173 CreateListHead(&L,10); 174 printf("\n"); 175 length = ListLength(L); 176 printf("%d\n", length); 177 printf("總體建立L的元素(頭插法):\n"); 178 ListTraverse(L); 179 printf("\n"); 180 h = L->next; 181 while(h){ 182 printf("%d ", h->data); 183 h = h->next; 184 } 185 printf("\n"); 186 ListReverse2(L); 187 // printf("反轉指定位置3的元素\n"); 188 // ReverseSpecArea(L, 3); 189 printf("反轉指定位置5的元素\n"); 190 ReverseSpecArea(L, 5); 191 192 getch(); 193 return 0; 194 }
四、判斷一個棧是否是「迴文」(判斷一個字符串是否是迴文)spa
思路:將一個字符串依次所有入棧,而後再出棧,依次比較每一個字符是否相等,若存在一個不等即不是迴文,當所有相等時即爲迴文3d
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<conio.h> 4 #include<math.h> 5 #include<time.h> 6 #include <string.h> 7 8 typedef int Status;/* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */ 9 typedef int ElemType;/* ElemType類型根據實際狀況而定,這裏假設爲int */ 10 typedef int SElemType; 11 12 #define MAXSIZE 20 13 #define OK 1 14 #define ERROR 0 15 #define TRUE 1 16 #define FALSE 0 17 //定義棧對象 18 typedef struct{ 19 SElemType data[MAXSIZE]; 20 int top;//指示棧頂元素 21 }SqStack; 22 //初始化棧 23 Status initStack(SqStack* S){ 24 S->top = -1; 25 return OK; 26 } 27 Status visit(SElemType c) 28 { 29 printf("%d ",c); 30 return OK; 31 } 32 /* 從棧底到棧頂依次對棧中每一個元素顯示 */ 33 Status StackTraverse(SqStack S) 34 { 35 int i; 36 i=0; 37 while(i<=S.top) 38 { 39 visit(S.data[i++]); 40 } 41 printf("\n"); 42 return OK; 43 } 44 //入棧 45 Status push(SqStack* S, SElemType e){ 46 //首先判斷是否棧滿 47 if(S->top == MAXSIZE - 1){ 48 return ERROR; 49 } 50 S->top++; /* 棧頂指針增長一 */ 51 S->data[S->top] = e; 52 return OK; 53 } 54 /* 若棧不空,則刪除S的棧頂元素,用e返回其值,並返回OK;不然返回ERROR */ 55 Status Pop(SqStack *S,SElemType *e) 56 { 57 if(S->top==-1)//爲空 58 return ERROR; 59 *e=S->data[S->top]; /* 將要刪除的棧頂元素賦值給e */ 60 S->top--; /* 棧頂指針減一 */ 61 return OK; 62 } 63 ElemType Pop1(SqStack *S) 64 { 65 if(S->top==-1)//爲空 66 return ERROR; 67 ElemType temp; 68 temp = S->data[S->top]; /* 將要刪除的棧頂元素賦值給e */ 69 S->top--; /* 棧頂指針減一 */ 70 return temp; 71 } 72 73 /* 若棧不空,則用e返回S的棧頂元素,並返回OK;不然返回ERROR */ 74 ElemType GetTop(SqStack S) 75 { 76 ElemType topElement; 77 if (S.top==-1) 78 return ERROR; 79 else 80 return S.data[S.top]; 81 82 } 83 84 int main() 85 { 86 SqStack s1; 87 SqStack s2; 88 SqStack temps; 89 bool flag = true; 90 int opp = 0; 91 int j; 92 if(initStack(&s1)==OK && initStack(&s2)==OK && initStack(&temps)==OK) 93 { 94 printf("順序棧初始化成功。"); 95 StackTraverse(s1); 96 StackTraverse(s2); 97 StackTraverse(temps); 98 } 99 char* str = "asfdasegf"; 100 char* str1 = "adfghgfda"; 101 for(int i = 0; i < 9; i++){ 102 push(&s1, str1[i]); 103 push(&temps, str1[i]); 104 } 105 StackTraverse(s1); 106 while((&temps)->top != -1){//不爲空 107 push(&s2, Pop1(&temps)); 108 } 109 StackTraverse(s2); 110 while((&s1)->top != -1){ 111 ElemType temp1 = Pop1(&s1); 112 ElemType temp2 = Pop1(&s2); 113 if(temp1 != temp2){ 114 printf("temp1 = %d ", temp1); 115 printf("\n"); 116 printf("temp2 = %d ", temp2); 117 printf("\n"); 118 printf("不是迴文!"); 119 flag = false; 120 break; 121 } 122 } 123 if(flag){ 124 printf("是迴文!"); 125 } 126 getch(); 127 }
此處採用的是順序棧的數據結構來實現的,也能夠採用鏈棧的結構處理指針
對於判斷一個字符串是不是迴文的問題能夠採用分別從字符串兩端遍歷的方式,逐個比較來斷定code
實現時需採用兩個指針變量分別指向頭和尾:front和rear對象
1 bool IsPalindrome(const char *s, int n) 2 { 3 //非法輸入 4 if (s == NULL || n < 1) 5 return false; 6 char *front, *back; 7 8 //初始化頭指針和尾指針 9 front = s; 10 back = s + n - 1; 11 12 while (front < back) 13 { 14 if (*front != *back) 15 return false; // 不是迴文,當即返回 16 ++front; 17 --back; 18 } 19 return true; // 是迴文 20 }
此方法效率較高,時間複雜度:O(n),空間複雜度:O(1)blog
固然,從中間向兩邊掃也是可行的:字符串
1 bool IsPalindrome2(const char *s, int n) 2 { 3 if (s == NULL || n < 1) 4 return false; // 非法輸入 5 char *first, *second; 6 7 int m = ((n >> 1) - 1) >= 0 ? (n >> 1) - 1 : 0; // m is themiddle point of s 右移一位至關於除以2 8 first = s + m; 9 second = s + n - 1 - m; 10 11 while (first >= s) 12 if (s[first--] != s[second++]) 13 return false; // not equal, so it's not apalindrome 14 return true; // check over, it's a palindrome 15 }
時間複雜度:O(n),空間複雜度:O(1)
一、判斷一條單向鏈表是否是「迴文」
分析:對於單鏈表結構,能夠用兩個指針從兩端或者中間遍歷並判斷對應字符是否相等。但這裏的關鍵就是如何朝兩個方向遍歷。因爲單鏈表是單向的,因此要向兩個方向遍歷的話,能夠採起經典的快慢指針的方法,即先位到鏈表的中間位置,再將鏈表的後半逆置,最後用兩個指針同時從鏈表頭部和中間開始同時遍歷並比較便可。
後面會具體實現