演算法要求:在單鏈表按公升序插入乙個值。成功插入返回1,已存在返回0,插入失敗返回-1。
結點結構:
typedef struct node
node;
c語言新手寫單鏈表的有序插入演算法可能會寫出下面的演算法: int list_insert(node *list, int value)
// 已存在,返回0
if (p!=null && p->value==value)
return 0;
new = (node*)malloc(sizeof(node));
if (!new)
return -1; // 失敗,返回-1
new->value = value;
new->next = p;
q->next = new;
return 1;
}仔細看,這是乙個有bug的**。如果要插入的值比鍊錶第乙個結點的值小,那麼應該插入在第乙個結點之前。這樣就應該修改頭結點的指標。但是,這個**卻實現不了這樣的功能。
經過以下修改可以修正這個bug。
int list_insert(node **list, int value)
// 已存在,返回0
if (p!=null && p->value==value)
return 0;
new = ( node*)malloc(sizeof(node));
if (!new)
return -1; // 失敗,返回-1
new->value = value;
new->next = p;
if (q == null) // 插入在第乙個位置,改變頭結點指標
*list = new;
else // 插入位置不是第乙個位置
q->next = new;
return 1;
}這個**沒有bug了。思路清晰。但是卻有冗餘。有最後要判斷是不是應該插入到鍊錶的第乙個位置。如果忘了判斷,還是會寫出第乙個**那樣的bug出來。下面有乙個改進的**。
int list_insert(node **pnext, int value)
// 已存在,返回0
if (p!=null && p->value==value)
reutrn 0;
new = (node*)malloc(sizeof(node));
if (!new)
return -1; // 失敗,返回-1
new->value = value;
new->next = current;
*pnext->new;
return 1;
}這個演算法不用考慮插入的是不是第一位置,因為它已經跟其他的操作一樣的。如果插入的是在第一位置,那麼*pnext已經修改了頭結點的指標。如果不是第乙個位置,也可以正確插入。
說明下,這兒傳入的引數是頭節點的位址,而不是頭節點,這點主要是針對當插入的數時最小的情況,當插入的值比已有鍊錶中所有的值都小時,就得修改頭節點,這時就只有傳入指標的指標,也就是頭結點的位址。
另外乙個就是這裡面沒移動一次節點,都取了當前節點位址來賦值給linkp,這也是針對頭結點這個特殊節點來的,以為我們插入乙個節點,就是要找到插入點的上乙個節點的link,而這個link可能是普通節點的link,也有可能是頭結點,
linkp = &t->link;就是來抽象這兩種不同的情況,把這情況的節點的屬性都看成一種節點。
在無頭單鏈表的乙個節點前插入乙個節點(不能遍歷)
例如 無頭鍊錶 a b c d 在節點c前面插入乙個節點 思路 乾坤大挪移 在c的後插入乙個節點,可以將c後面新插入的節點q的值與c的值交換 即可實現c節點之前插入節點的功能 void listentry listnode phead,linknode pos datatype value 若pos...
在無頭單鏈表的乙個非頭節點前插入乙個節點
思路 由於單鏈表的單向性,所以我們現在這個非頭結點的後面插入乙個節點,然後在交換這兩個節點就可以了。標頭檔案 鍊錶定義 include include include typedef int datatype typedef struct strnode node typedef struct st...
反轉乙個單鏈表
思路二 反轉乙個鍊錶 示例 結構體定義 先對原鍊錶做頭刪操作,再對新鍊錶做頭插定義乙個新head頭指標,標記為newhead,將它初始為null,並非指向null,最後我們選擇返回這個newhead指標作為新鍊錶的頭指標。定義乙個結點node作為 臨時中轉站 初始化與否並無大影響。進行迴圈遍歷鍊錶各...