c语言编程切片stl1005无标题,C语言实现简单的单向链表(创建、插入、删除)及等效STL实现代码...
實現個算法,懶得手寫鏈表,于是用C++的forward_list,沒有next()方法感覺很不好使,比如一個對單向鏈表的最簡單功能要求:
input:
1 2 5 3 4
output:
1->2->5->3->4
相當于僅僅實現了插入、遍歷2個功能(當然遍歷功能稍微修改就是銷毀鏈表了)
用純C寫了份測試代碼
/*基本數據結構的定義以及函數的聲明 */
typedef intElemType;
typedefstructNode
{
ElemType elem;struct Node*next;
} Node,* NodePtr, **ForwardList;
NodePtr createNode(ElemType x);voidshowList(ForwardList lst);voiddestroyList(ForwardList lst);//創建元素為x的節點并插入到節點where后面//若where為NULL, 則插入到鏈表lst的首部作為首節點//返回新節點的指針
NodePtr insertAfterNode(NodePtr where, ElemType x,
ForwardList lst);
/*鏈表相關函數的具體實現*/NodePtr createNode(ElemType x)
{
NodePtr pNode= (NodePtr) malloc(sizeof(Node));if (pNode ==NULL) {
perror("malloc");
exit(1);
}
pNode->elem =x;
pNode->next =NULL;returnpNode;
}
NodePtr insertAfterNode(const NodePtr where,
ElemType x, ForwardList lst)
{
NodePtr pNode=createNode(x);if (where ==NULL) {*lst =pNode;
}else{
pNode->next = where->next;where->next =pNode;
}returnpNode;
}voidshowList(ForwardList lst)
{
printf("顯示鏈表:");
NodePtr curr= *lst;while (curr->next !=NULL) {
printf("%d->", curr->elem);
curr= curr->next;
}
printf("%d", curr->elem);
}voiddestroyList(ForwardList lst)
{
printf("銷毀鏈表:");
NodePtr curr= *lst;while (curr !=NULL) {
NodePtr next= curr->next;
printf("%d", curr->elem);free(curr);
curr=next;
}
printf("");
}
/*測試代碼*/
intmain()
{
NodePtr head=NULL;
initListFromStdin(&head);
showList(&head);
destroyList(&head);return 0;
}
三個部分都是寫在一份代碼里(forward_list.c)的,測試結果如下
$ lsdata.inforward_list.c
$cat data.in
1 2 5 3 4$gcc forward_list.c -std=c99
$ ./a.out 2->5->3->4銷毀鏈表:1 2 5 3 4
由于是不需要考慮周全的C代碼,所以很多C++的一些工程性的技巧不需考慮,比如模板、const,說起來之前沒把C代碼封裝成函數的時候就曾經導致鏈表的頭節點被修改,最后銷毀鏈表時,遍歷后頭節點直接指向了最后一個節點,導致前4個節點都沒被銷毀。如果合理地使用const,在編譯期就能檢查出來。
嘛,其實這么一寫下來,C++的forward_list版本也就寫出來了,畢竟我的鏈表插入函數就是模仿forward_list的,但是寫出來有點別扭。因為需要遍歷到倒數第2個節點停止,最后代碼如下
#include
#include
using namespace std;
// 取得前向迭代器it的下一個迭代器
template
FwIter nextIter(FwIter it)
{
return ++it;
}
int main()
{
forward_list lst;
int x;
for (auto it = lst.before_begin();
fscanf(stdin, "%d", &x) == 1;
)
{
it = lst.emplace_after(it, x);
}
// 按照a0->a1->...->an的格式輸出
auto it = lst.begin();
while (nextIter(it) != lst.end())
{
printf("%d->", *it++);
}
printf("%d
", *it);
return 0;
}
既然C++不提供next()函數那就只有手寫一個,因為迭代器傳參數時拷貝了一份,所以nextIter()直接返回++it并不會對原迭代器進行修改,而是修改的原迭代器的拷貝。
注意一點就是,在順序插入構建鏈表時需要記錄鏈表最后一個節點,跟我的C代碼實現風格一致(好吧其實我本來就是仿STL實現的)。
那么初始值就是before_begin()而不是begin(),因為空鏈表不存在begin(),確切的說空鏈表的初始節點為NULL。
測試代碼,這里_M_node是glibc++的forward_list迭代器底層實現部分,并不是跨平臺代碼。迭代器相當于把節點地址進行了一層封裝,而_M_node則是節點地址。
#include #include
intmain()
{
std::forward_listlst;
printf("begin()地址: %p", lst.begin()._M_node);
printf("before_begin()地址: %p", lst.before_begin()._M_node);return 0;
}
結果如下:
$ g++ test.cc -std=c++11$ ./a.out
begin()地址: (nil)
before_begin()地址:0x7fffb0896b60
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的c语言编程切片stl1005无标题,C语言实现简单的单向链表(创建、插入、删除)及等效STL实现代码...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux进程中对信号的屏蔽,linux
- 下一篇: c语言ungetc参数,关于一些C语言标