icoding复习1,2
icoding復習 1
 鏈表 倒數查找
1. 已知一個帶有表頭結點的單鏈表, 假設鏈表只給出了頭指針L。在不改變鏈表的前提下,請設計一個盡可能高效的算法,
 查找鏈表中倒數第k個位置上的結點(k為正整數)。
 函數原型為:int lnk_search(LinkList L, int k, ElemType* p_ele)
 若查找成功,函數通過指針參數 p_ele 返回該結點 data 域的值,此時函數返回 1;否則,函數返回 0。相關定義如下:
struct _lnklist{
 ? ? ElemType data;
 ? ? struct _lnklist *next;
 };
typedef struct _lnklist Node;
 typedef struct _lnklist *LinkList;
#include 
 #include 
 #include "list.h" // 請不要刪除,否則檢查不通過
int lnk_search(LinkList L, int k, ElemType* p_ele){
 ?? ?int i, length;
 ?? ?Node *p;
 ?? ?
 ?? ?
 ?? ?for(i = 0, p = L; p; i++)
 ?? ??? ?p = p->next;
 ?? ??? ?
 ?? ?length = i;
 ?? ?if(length == 0 || length < k)?? ?return 0;
 ?? ?
 ?? ?for(i = 0, p = L; i <= length - k; i++)//!!取等,注意邊界?
 ?? ??? ?p = p->next;
 ?? ??? ?
 ?? ?*p_ele = p->data;
 ?? ?
 ?? ? return 1;
 }
 2. 鏈表 合并
設線性表A=(a1, a2,…,am),B=(b1, b2,…,bn),試寫一個按下列規則合并A、B為線性表C的算法,使得:
 C= (a1, b1,…,am, bm, bm+1, …,bn) 當m≤n時;
 或者
 C= (a1, b1,…,an, bn, an+1, …,am) 當m>n時。
 線性表A、B、C均以單鏈表作為存儲結構,且C表利用A表和B表中的結點空間構成。
 注意:單鏈表的長度值m和n均未顯式存儲。
 函數的原型如下:
 void lnk_merge(LinkList A, LinkList B, LinkList C)
 即將A和B合并為C,其中 C 已經被初始化為空單鏈表
 相關定義如下:
 //注意:線性表可以是鏈表?
 struct _lnklist{
 ? ? ElemType data;
 ? ? struct _lnklist *next;
 };
typedef struct _lnklist Node;
 typedef struct _lnklist *LinkList;
 #include 
 #include 
 #include "list.h" // 請不要刪除,否則檢查不通過
void lnk_merge(LinkList A, LinkList B, LinkList C){
 ?? ?Node *p, *q, *c;
 ?? ?bool flag = true;//小寫!python大寫首字母 不用包含bool頭文件?
 ?? ?
 ?? ?c = C;//c尾指針?
 ?? ?p = A->next;
 ?? ?q = B->next;
 ?? ?
 ?? ?while(p && q){
 ?? ??? ?if(flag){
 ?? ??? ??? ?c->next = p;
 ?? ??? ??? ?c = p;
 ?? ??? ??? ?p = p->next;
 ?? ??? ??? ?flag = false;
 ?? ??? ?}?
 ?? ??? ?else{
 ?? ??? ??? ?c->next = q;
 ?? ??? ??? ?c = q;
 ?? ??? ??? ?q = q->next;
 ?? ??? ??? ?flag = true;
 ?? ??? ?}
 ?? ?}
 ?? ?
 ?? ?if(p)
 ?? ??? ?c->next = p;
 ?? ?else
 ?? ??? ?c->next = q;
 ?? ??? ?
 ?? ?free(A);
 ?? ?free(B);//!!
 }
 3. 順序表 刪除指定范圍
 設計一個高效的算法,從順序表L中刪除所有值介于x和y之間(包括x和y)的所有元素(假設y>=x),
 要求時間復雜度為O(n),空間復雜度為O(1)。
 函數原型如下:
 void del_x2y(SeqList *L, ElemType x, ElemType y);
 相關定義如下:
struct _seqlist{
 ? ? ElemType elem[MAXSIZE];
 ? ? int last;
 };
 typedef struct _seqlist SeqList;
 #include "list.h" // 請不要刪除,否則檢查不通過
 #include 
 #include 
void del_x2y(SeqList *L, ElemType x, ElemType y){
 ?? ?int i, j = 0;
 ?? ??
 ?? ?for(i = 0; i < L->last; i++){
 ?? ??? ?if(L->elem[i] < x || L->elem[i] > y)
 ?? ??? ??? ?L->elem[j++] = L->elem[i];?? ?
?? ?L->last = j - 1;//不用設置delta增量記錄刪除的數量?
 }
 4. 鏈表 刪除范圍內結點
已知線性表中的元素(整數)以值遞增有序排列,并以單鏈表作存儲結構。
 試寫一高效算法,刪除表中所有大于mink且小于maxk的元素(若表中存在這樣的元素),
 分析你的算法的時間復雜度。
鏈表結點定義如下:
 struct _lnklist{
 ? ? ElemType data;
 ? ? struct _lnklist *next;
 };
 typedef struct _lnklist Node;//結構標記?
 typedef struct _lnklist *LinkList;//!!?
 函數原型如下:
 void lnk_del_x2y(LinkList L, ElemType mink, ElemType maxk)
#include "list.h" // 請不要刪除,否則檢查不通過
 #include 
 #include 
void lnk_del_x2y(LinkList L, ElemType mink, ElemType maxk){
 ?? ?Node *p, *temp;
 ?? ?
 ?? ?for(p = L->next; p; p = p->next){
 ?? ??? ?if(p->data < maxk && p->data > mink){
 ?? ??? ??? ?temp = p;
 ?? ??? ??? ?p = p->next;
 ?? ??? ??? ?free(p);
 ?? ??? ?}
 ?? ??? ?if(p->data > maxk)
 ?? ??? ??? ?break;
 ?? ?}
 }
 //解法2為指針跟蹤技術?
 void lnk_del_x2y(LinkList L, ElemType mink, ElemType maxk)
 {
 ? ? Node *p, *pre;
 ? ? pre = L;
 ? ? p = L->next;
 ? ? for (; p;) {
 ? ? ? ? if (p->data > mink && p->data < maxk) {
 ? ? ? ? ? ? pre->next = p->next;
 ? ? ? ? ? ? free(p);
 ? ? ? ? ? ? p = pre->next;
? ? ? ? } else {
 ? ? ? ? ? ? pre = p;
 ? ? ? ? ? ? p = p->next;
 ? ? ? ? }
 ? ? }
 }
5. 順序表 刪除重復
編寫算法,在一非遞減的順序表L中,刪除所有值相等的多余元素。
 要求時間復雜度為O(n),空間復雜度為O(1)。
 函數原型如下:
 void del_dupnum(SeqList *L)
相關定義如下:
 struct _seqlist{
 ? ? ElemType elem[MAXSIZE];
 ? ? int last;
 };
 typedef struct _seqlist SeqList;
#include "list.h" // 請不要刪除,否則檢查不通過
 #include 
 #include 
 //這里是線性表中的順序表,不是鏈表!?
 void del_dupnum(SeqList *L){
 ?? ?int i, j = 0, delta = 0;
 ?? ?//一次遍歷達到時間復雜度?
 ?? ?for(i = 0; i < L->last; i++){
 ?? ??? ?if(L->elem[i] != L->elem[i+1])
 ?? ??? ??? ?L->elem[j++] = L->elem[i];
 ?? ??? ?else
 ?? ??? ??? ?delta++;
 ?? ?}
 ?? ?
 ?? ?L->last -= delta;
 }
 //解法2 不用設置delta增量?
 void del_dupnum(SeqList* L)
 {
 ? ? int i, j = 1;
 ? ? for (i = 1; i <= L->last; i++) {
 ? ? ? ? if (L->elem[i] != L->elem[i - 1]) {
 ? ? ? ? ? ? L->elem[j++] = L->elem[i];
 ? ? ? ? }
 ? ? }
 ? ? L->last = j - 1;
 }
6. 順序表 數據調整
已知順序表L中的數據元素類型為int。設計算法將其調整為左右兩部分,
 左邊的元素(即排在前面的)均為奇數,右邊所有元素(即排在后面的)均為偶數,
 并要求算法的時間復雜度為O(n),空間復雜度為O(1)。
函數原型如下:
 void odd_even(SeqList *L);
相關定義如下:
 struct _seqlist{
 ? ? ElemType elem[MAXSIZE];
 ? ? int last;
 };
 typedef struct _seqlist SeqList;
#include "list.h" // 請不要刪除,否則檢查不通過
 #include 
 #include 
#define N 2?
 //題目描述不清晰
 //偶數內部排序順序未知?
 void odd_even(SeqList *L){
 ?? ?int i, j;
 ?? ?int x;
 ?? ?
 ?? ?for(i = 0, j = 0; i < L->last && i + 1 != L->last - j; i++){
 ?? ?//for的另一種寫法for (i = 0, j = 0; i <= L->last - j; i++) {?
 ?? ??? ?if(!(L->elem[i] % N)){//偶數?
 ?? ??? ??? ?x = L->elem[L->last-j];
 ?? ??? ??? ?L->elem[L->last-j] = L->elem[i];
 ?? ??? ??? ?L->elem[i] = x;
 ?? ??? ??? ?i--;
 ?? ??? ??? ?j++;
 ?? ??? ?}
 ?? ?}
 }
 ?
icoding復習2?
1. 棧 后綴表達式計算
 (1)如果是操作數,直接入棧
 (2)如果是操作符op,連續出棧兩次,得到操作數x 和 y,計算 x op y,并將結果入棧。
 #define Stack_Size 50
 typedef struct{
 ? ? ElemType elem[Stack_Size];
 ? ? int top;
 }Stack;
bool push(Stack* S, ElemType x);
 bool pop(Stack* S, ElemType *x);
 void init_stack(Stack *S);
 其中,棧初始化的實現為:
 void init_stack(Stack *S){
 ? ? S->top = -1;
 }
 需要完成的函數定義為:int compute_reverse_polish_notation(char *str);
 函數接收一個字符指針,該指針指向一個字符串形式的后綴表達式,函數返回該表達式的計算結果。
#include 
 #include 
 #include "list.h" // 請不要刪除,否則檢查不通過
//字符指針!!!!!!!!!!!!
 //易錯?
 int compute_reverse_polish_notation(char* str)//光禿禿的*str 怎么用要知道?
 {
 ? ? int i = 0;
 ? ? Stack S;
 ? ? //沒必要*S?
 ? ? init_stack(&S);
 ? ? ElemType _push, num1, num2;
 ? ??
 ? ? //str[i]等價于*(str+i)?
 ? ? while (str[i] != '\0') {
 ?? ?//?? ?先判空 再判空格 再判數字和符號 數字判斷是幾位數?
 ? ? ? ? if (str[i] != ' ') {
 ? ? ? ? ?? ?
 ? ? ? ? ? ? if (str[i] >= '0' && str[i] <= '9') { //!!
 ? ? ? ? ? ? ? ? _push = 0;
 ? ? ? ? ? ? ? ??
 ? ? ? ? ? ? ? ? while (str[i] != ' ') {
 ? ? ? ? ? ? ? ? ?? ?_push *= 10;
 ? ? ? ? ? ? ? ? ? ? _push += (str[i] - '0');?
 ? ? ? ? ? ? ? ? ? ? //一個數字一個數字的壓入 , 判斷位數?
 ? ? ? ? ? ? ? ? ? ? i++;
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? ? push(&S, _push);
 ? ? ? ? ? ? ? ? //每次_push會變, push函數里面top會++
 ?? ??? ??? ??? ?//切記?
 ? ? ? ? ? ? } else {
 ? ? ? ? ? ? ?? ?//格外小心彈出來的順序
 ?? ??? ??? ??? ?//先彈出來的符號對它作用?
 ? ? ? ? ? ? ? ? pop(&S, &num2);
 ? ? ? ? ? ? ? ? pop(&S, &num1);
 ? ? ? ? ? ? switch (str[i]) {
 ? ? ? ? ? ? ? ? case '+': {
 ? ? ? ? ? ? ? ? ? ? num1 += num2;//注意兩個操作數的順序?
 ? ? ? ? ? ? ? ? ? ? break;//!!!!!
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? ? case '-': {
 ? ? ? ? ? ? ? ? ? ? num1 -= num2;
 ? ? ? ? ? ? ? ? ? ? break;
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? ? case '*': {
 ? ? ? ? ? ? ? ? ? ? num1 *= num2;
 ? ? ? ? ? ? ? ? ? ? break;
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? ? case '/': {
 ? ? ? ? ? ? ? ? ?? ?if(num2)//判除數?
 ? ? ? ? ? ? ? ? ? ? ?? ?num1 /= num2;
 ? ? ? ? ? ? ? ? ? ? break;
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? ? ? case '%': {
 ? ? ? ? ? ? ? ? ? ? if(num2)?
 ?? ??? ??? ??? ? ?? ? ? num1 %= num2;
 ? ? ? ? ? ? ? ? ? ? break;
 ? ? ? ? ? ? ? ? }
 ? ? ? ? ? ? }
 ? ? ? ? ? ? push(&S, num1);
 ? ? ? ? ? ? }
 ? ? ? ? }
 ? ? ? ? i++;
 ? ? }
 ? ? pop(&S, &num1);
 ? ? //最后的返回值也要彈出來?
 ? ? return num1;
 }
 2. 隊列 循環鏈表表示隊列
 假設以帶頭結點的循環鏈表表示隊列,并且只設一個指針指向隊尾元素結點(注意不設頭指針),請完成下列任務:
 1: 隊列初始化,成功返回真,否則返回假: bool init_queue(LinkQueue *LQ);
 2: 入隊列,成功返回真,否則返回假: bool enter_queue(LinkQueue *LQ, ElemType x);
 3: 出隊列,成功返回真,且*x為出隊的值,否則返回假 bool leave_queue(LinkQueue *LQ, ElemType *x);
 typedef struct _QueueNode {
 ? ? ElemType data; ? ? ? ? ?/*數據域*/
 ? ? struct _QueueNode *next; ? ? ?/*指針域*/
 }LinkQueueNode, *LinkQueue;
 #include 
 #include 
 #include "list.h" // 請不要刪除,否則檢查不通過
bool init_queue(LinkQueue *LQ){
 ?? ?
 ?? ?//注意這里是給*LQ分配空間,不是LQ; 類比Node *p對于p的空間分配?
 ?? ?if(!(*LQ = (LinkQueue)malloc(sizeof(LinkQueueNode)))) return false;
 ?? ?
 ?? ?(*LQ)->next = *LQ;
 ?? ?return true;
 }
 //!!!
 bool enter_queue(LinkQueue *LQ, ElemType x){
 ?? ?LinkQueueNode *p;
 ?? ?
 ?? ?if(!(p = (LinkQueueNode *)malloc(sizeof(LinkQueueNode)))) return false;
 ?? ?
 ?? ?p->data = x;
 ?? ?//LQ為隊尾指針
 ?? ?//這一步順序不要顛倒,循環隊列連接到頭結點?
 ?? ?p->next = (*LQ)->next;
 ?? ?//尾插入?
 ?? ?(*LQ)->next = p;
 ?? ?*LQ = p;?
 ?? ?
 ?? ?return true;?
 }
 ??
 //!!!
 bool leave_queue(LinkQueue* LQ, ElemType* x)
 {
 ? ? LinkQueueNode *first, *p;
 ? ? //first為頭結點?
 ? ? first = (*LQ)->next;
 ? ? if (first == *LQ)
 ? ? ? ? return false;
 ? ? //注意的是頭節點為空, 并且是自然形成的
 ? ??
 ? ? p = first->next;
 ? ? *x = p->data;
 ? ? if (p != *LQ) //這種情況只有一個尾結點可以釋放
 ? ? ? ? first->next = p->next;
 ? ? else {//!!!
 ? ? ? ? *LQ = (*LQ)->next;//LQ變為頭結點,尾指針指向頭結點?
 ? ? ? ? (*LQ)->next = *LQ; //自己構成空循環
 ? ? }
 ? ? free(p);
 ? ? return true;
 }
總結
以上是生活随笔為你收集整理的icoding复习1,2的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 单反相机什么牌子好?单反相机哪款好?
- 下一篇: icoding复习6 图
