c语言链表与字符结合,C语言实现双链表的(终端)添加和查询
文章如果有寫的不對的地方,歡迎指正^^
雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個數(shù)據(jù)結點中都有兩個指針,分別指向直接后繼和直接前驅。所以,從雙向鏈表中的任意一個結點開始,都可以很方便地訪問它的前驅結點和后繼結點。一般我們都構造雙向循環(huán)鏈表。雙鏈表wiki
通過雙鏈表可以快速的了解c語言中的指針和內(nèi)存的關系
細節(jié)
指針變量存儲的是內(nèi)存的地址,可以理解為一個存儲內(nèi)存地址的符號
聲明的是類型,定義的是變量。聲明的時候不分配內(nèi)存,int i;屬于定義。
結構體聲明時不分配內(nèi)存,定義變量的時候才分配struct linked_list link_1;
指針變量相互賦值,傳遞的是所代表的內(nèi)存地址
函數(shù)接受字符串的時候,形參要用char *來代表字符串數(shù)組的首地址
-> 用來表示調(diào)用結構體指針所代表的變量的域,如果用.則代表結構體變量調(diào)用自己的域
判斷一個指針是否為空,用== NULL
鏈表實現(xiàn)方案
/*
describe linked_list
_
| |__ _ _ __ _
| '_ \| | | |/ _` |
| |_) | |_| | (_| |
|_.__/ \__,_|\__, |
|___/
*/
#include
#include
struct linked_list {
struct linked_list *next, *prev;
char *title;
};
/* 聲明結構體指針變量,會在內(nèi)存中開辟空間,存儲指針 */
struct linked_list * current,* prev, *head;
void list_add(char *);
void list_search();
void list_reverse_search();
int main(void) {
list_add("-");
list_add("--");
list_add("---");
list_add("----");
list_add("-----");
list_search();
list_reverse_search();
}
void list_add(char *title) {
/* 將新申請的內(nèi)存的首地址給結構體指針變量 */
current = (struct linked_list *)malloc(sizeof(struct linked_list));
/* 初始化當前結構體,新增元素的next始終是NULL */
current->next = NULL;
current->title = title;
/* prev元素是否已經(jīng)存在了,是否存在前輩元素,來判斷是否是首次添加元素*/
if(prev == NULL) {
/* 如果不存在說明,current是第一個添加進來的元素 */
current->prev = NULL;
/* 設置為首元素,這里current和head現(xiàn)在指向的是同一個內(nèi)存地址 */
head = current;
}else {
/* 如果存在前輩元素,將當前元素的prev設置為前輩元素的地址,并且將前輩元素的next設置為當前元素的地址 */
current->prev = prev;
prev->next = current;
}
/* 將當前指針所代表元素的地址,交給prev指針符號 ,現(xiàn)在head和prev指向同一個地址*/
prev = current;
/* 首次添加元素head是沒有next的,第二次添加的時候,prev 的next設置為了新增元素地址,所以head的next也發(fā)生了改變 ( 添加第2個元素的時候,才會重寫上個元素的next值)*/
}
/* 鏈表正序搜索 */
void list_search() {
while(head) {
printf("%s\n", head->title);
head = head->next;
}
}
/* 倒序搜索 */
void list_reverse_search() {
while(current) {
printf("%s\n", current->title);
current = current->prev;
}
}
終端向鏈表添加元素
我們來強化一下,通過終端來不停地向鏈表中添加元素。并且每次回車之后,都打印出整個列表的元素。
要點
聲明定義字符串數(shù)組的時候,值不能用變量
我們要求每次都要保存填寫的元素值,所以每次都需要重新開辟一個內(nèi)存空間,給新的struct,由于個struct中都保存的是title的指針,所以新增加的元素的title也需要重新開辟內(nèi)存空間來存儲。
由于每次都需要進行打印鏈表,所以head要注意不能被覆寫。所以重新定義一個struct linked_list變量來做一個中間變量。
#include
#include
#include
struct linked_list {
struct linked_list *next, *prev;
char *title;
};
struct linked_list *head,*current,*above;
struct linked_list head_cp;
void list_add(char *);
void list_search();
int main(int argc, char *argv[]) {
char title[10];
while(scanf("%s",title) > 0) {
list_add(title);
/* 每次添加到鏈表之后,都會進行打印整個鏈表 */
list_search();
}
/*
這樣初始化是錯誤的
error: array initializer must be an initializer list or string literal
“數(shù)組的初始化,必須是一個列表或者是字面的字符串”
char title[] = *(argv+1);
*/
}
void list_add(char *t) {
/* 分配內(nèi)存 */
current = (struct linked_list *)malloc(sizeof(struct linked_list));
/* title 是一個內(nèi)存空間的首地址,這里重新分配內(nèi)存的原因是,每次scanf都會重寫t指針下的內(nèi)容,導致整個鏈式里面所有的title都發(fā)生變化 */
char *title = (char *)malloc(sizeof(*t));
/* 將t指針指向的內(nèi)容copy到title指針指向的內(nèi)存中 */
strcpy(title,t);
/* 初始化結構體域 */
current->prev = NULL;
current->next = NULL;
/* 指向新內(nèi)存中的title */
current->title = title;
if(above == NULL) {
head = current;
}else {
current->prev = above;
above->next = current;
}
above = current;
}
void list_search() {
/* 這將head指向的內(nèi)容賦值給新開辟的結構體變量,這里不是給的地址,給的是內(nèi)容 */
head_cp = *head;
while(head_cp.title) {
printf(">>%s\n", head_cp.title);
if(head_cp.next != NULL) {
head_cp = *(head_cp.next);
}else {
return;
}
}
}
操作結果
1 /* 回車 */
>>1
2 /* 回車 */
>>1
>>2
3 /* 回車 */
>>1
>>2
>>3
4 /* 回車 */
>>1
>>2
>>3
>>4
能不能不手動分配title的內(nèi)存空間呢?
當然可以。下面代碼中我們修改了struct的結構將原來的char *title修改為char title[10],這樣每次定義結構體變量的時候,內(nèi)存作為struct的一部分一起分配好了。
那么我們在add元素的時候,就需要將scanf獲取到的變量,通過strcpy(current->title,title)的方式,寫入到char title[10]開辟的內(nèi)存空間中。
還需要修改list_search方法中的while判斷,不能再判斷指針是否為NULL的方式來判斷是否存在title內(nèi)容,而是要判斷字符串的長度strlen(head_cp.title) == 0。
但是最后一種修改結構體的方式無法動態(tài)分配內(nèi)存,每次生成的字符串的長度都是10,會浪費內(nèi)存。
#include
#include
#include
struct linked_list {
struct linked_list *next, *prev;
char title[10];
};
struct linked_list *head,*current,*above;
struct linked_list head_cp;
void list_add(char *);
void list_search();
int main(int argc, char *argv[]) {
char title[10];
while(scanf("%s",title) > 0) {
list_add(title);
/* 每次添加到鏈表之后,都會進行打印整個鏈表 */
list_search();
}
/*
這樣初始化是錯誤的
error: array initializer must be an initializer list or string literal
“數(shù)組的初始化,必須是一個列表或者是字面的字符串”
char title[] = *(argv+1);
*/
}
void list_add(char *title) {
/* 分配內(nèi)存 */
current = (struct linked_list *)malloc(sizeof(struct linked_list));
/* 初始化結構體域 */
current->prev = NULL;
current->next = NULL;
/* 這里current->title是字符串數(shù)組的首地址,是個指針 */
strcpy(current->title,title);
if(above == NULL) {
head = current;
}else {
current->prev = above;
above->next = current;
}
above = current;
}
void list_search() {
/* 這將head指向的內(nèi)容賦值給新開辟的結構體變量,這里不是給的地址,給的是內(nèi)容 */
head_cp = *head;
while(strlen(head_cp.title) != 0) {
printf(">>%s\n", head_cp.title);
if(head_cp.next != NULL) {
head_cp = *(head_cp.next);
}else {
return;
}
}
}
總結
以上是生活随笔為你收集整理的c语言链表与字符结合,C语言实现双链表的(终端)添加和查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 火狐linux版更改语言,Seleniu
- 下一篇: r语言x c(-1 -2),【软件】R语