算法之单向链表
1 链表结构体
/*结构体*/ typedef struct _link_node { struct _link_node* next; int data; }link_node;
- 注意点
- 定义结构体时,最好的顺序是由大到小的顺序定义结构体成员,如上,我先定义了
一个指针类型,然后又定义了一个 int类型变量,它会占用16个字节,如果你顺序
调过来,还是16个字节,但是它的效率会低很多,为什么会这样了?请看数据对齐相
关内容; 《数据对齐详解》
2 创建链表
/*1.创建链表*/ link_node* creat_node(int value) { link_node* pLinkNode; pLinkNode = (link_node*)malloc(sizeof(link_node)); if(NULL ==pLinkNode) printf("Failt"); pLinkNode->data = value; pLinkNode->next = NULL; return pLinkNode; }
3 打印链表
/*2.打印链表*/ void print_node(link_node* pLinkNode) { if(NULL == pLinkNode) { printf(" "); return ; } printf("%d ",pLinkNode->data); printf("p2=%p ",pLinkNode); print_node(pLinkNode->next); }
4 插入链表
/*4.链表插入数据*/ /* 插入位子从 0 开始 */ int _insert_node(link_node** pToNode, link_node* pDataNode, int place) { if( NULL == *pToNode ) { printf("超出链表长度,插入失败 "); return -1; } if(1==place ) { pDataNode->next = (*pToNode)->next; (*pToNode)->next=pDataNode; return 0; } _insert_node(&(*pToNode)->next, pDataNode, place-1); } void insert_node(link_node** pToNode, int place, int value) { link_node* pDataNode; pDataNode = creat_node(value); if(0 == place) { pDataNode->next = *pToNode; *pToNode = pDataNode; return; } if(place<0 ) /*和法性有问题,插入位子容易过大*/ { printf("插入位子错误"); return; } _insert_node(pToNode, pDataNode, place); }
5 删除链表
/*5.删除链表*/ #if 1 /* 递归方法 */ void delete_node(link_node** pNode) { link_node* pLinkNode; if(NULL==pNode || NULL==*pNode) { printf("afa "); return; } printf("1 "); pLinkNode = *pNode; *pNode=(*pNode)->next; free(pLinkNode); //printf("pdata=%d pnext=%p ",pLinkNode->data, pLinkNode->next); //测试 delete_node(pNode); } #else /*普通方法*/ void delete_node(link_node** pNode) { link_node *pLinkNode; while(NULL != *pNode) { pLinkNode=*pNode; *pNode=(*pNode)->next; free(pLinkNode); /*调试信息*/ //printf("pnp=%p pdp=%p ", pLinkNode,&(pLinkNode->data) ); //printf("pdata=%d pnext=%p ",pLinkNode->data, pLinkNode->next); } } #endif
- 注意事项
- 在我调试删除链表时发现一个奇怪现象
本奇葩现象在单向链表中发现
1.在带有指针域和数据域结构体中,用malloc()函数分配空间,再用free()函数
释放空间,在释放空间过程中,被释放空间的指针域会产生一个随机数,而数据域的
值不会发生任何改变,如果你通过被释放空间的指针域访问下一个地址,你可以在
数据域中看到一个随机的数据,但指针域所指的地址为NULL。 - 测试代码
#include
#include typedef struct _link_node { struct _link_node* next; int data; }link_node; int main() { link_node* pLinkNode; link_node* pNode; pLinkNode = (link_node*)malloc(sizeof(struct _link_node)); pNode = (link_node*)malloc(sizeof(struct _link_node)); pLinkNode->data = 16; pNode->data = 6; pLinkNode->next = pNode; printf("%p ",pNode); printf("前:pnp=%p pdp=%p ", pLinkNode,&(pLinkNode->data) ); printf("pdata=%d pnext=%p ",pLinkNode->data, pLinkNode->next); free(pNode); free(pLinkNode); printf("后:pnp=%p pdp=%p ", pLinkNode,&(pLinkNode->data) ); printf("pdata=%d pnext=%p ",pLinkNode->data, pLinkNode->next); printf("ndata=%d ",(pLinkNode->next)->data); printf("np=%p ",(pLinkNode->next)->next); return 0; }
6 删除结点
/*6.删除结点*/ void delete_one_node(link_node** pNode, int place) { link_node* pNext; if(NULL==*pNode || NULL==pNode) { printf("超出链表,删除失败 "); return; } if(1== place) { *pNode=(*pNode)->next; return; } if(2 == place) { pNext=(*pNode)->next; (*pNode)->next = pNext->next; free(pNext); return; } delete_one_node(&(*pNode)->next,place-1); }
7 查找数据
/*7. 查找数据*/ link_node* find_data(link_node** pNode, int value) { if(NULL==(*pNode)) { printf("not found ! "); return NULL; } if(value == ((*pNode)->data)) { return *pNode; } find_data(&(*pNode)->next, value); }
8 统计数据
/*8.统计数据*/ int count_node(link_node* pLinkNode) { if(NULL==pLinkNode) return 0; return 1+count_node(pLinkNode->next); }
9 测试代码
void main() { link_node* pLinkNode; link_node* pNode; int n; pLinkNode = creat_node(5); add_data(&pLinkNode, 7); add_data(&pLinkNode, 8); add_data(&pLinkNode, 9); print_node(pLinkNode); delete_node(&pLinkNode); print_node(pLinkNode); }