这篇文章也是为了复习下,同时为字典树做下准备
链表操作包括创建,删除,增加,排序,输出等操作,后续将代码贴上
单向链表: head ---->[NULL]
空链表:head---->[p1]---->[p2]...---->[pn]---->[NULL]
p1->next p2->next pn->next
#include <stdio.h>
#include <stdlib.h>
int n = 0; //节点个数
typedef struct db
{
int num;
int score;
struct db *next;//这个是创建链表的关键
};
#define LEN sizeof(struct db)
//返回值是链表表头
struct db *list_create()
{
struct db *head = NULL;//头节点
struct db *p1 = NULL; //p1保存创建的新节点的地址
struct db *p2 = NULL;
n = 0;//当前链表节点
p1 = (struct db*) malloc(LEN);
//重要的一步,要把p1保存下来
p2 = p1;
//还要判断有没有申请内存成功
if (NULL == p1)
{
return NULL;
}
else
{
printf("plz input num in node %d\n", n + 1);
scanf("%d %d", &p1->num, &p1->score);
}
while (0 != p1->num)
{
n += 1;
if (1 == n) //第一个节点
{
head = p1;
p2->next = NULL; //记住,相当于下一个节点是NULL,之前p1已经赋给了p2
}
else
{
p2->next = p1;//下一个节点
}
p2 = p1; //p1将要生成新的地址
p1 = (struct db*) malloc(LEN);
//还要判断有没有申请内存成功
if (NULL == p1)
{
return NULL;
}
printf("plz input num in node %d\n", n + 1);
scanf("%d %d", &p1->num, &p1->score);
}
//单向链表的结尾就是指向NULL
p2->next = NULL;
free(p1);
p1 = NULL;
return head;
}
void list_print(struct db *node)
{
struct db *p1 = NULL;
if (NULL == node)
{
return;
}
p1 = node->next;
printf("%d %d\n", node->num, node->score);
while (NULL != p1)
{
printf("%d %d\n", p1->num, p1->score);
p1 = p1->next;
}
return;
}
int list_search(struct db* node, int num)
{
int count = 0;
struct db *p1 = NULL;
if (NULL == node)
{
return 0;
}
if (num == node->num) count += 1;
p1 = node->next;
//printf("%d %d\n",node->num,node->score);
while (NULL != p1)
{
if (num == node->num) count += 1;
p1 = p1->next;
}
return count;
}
struct db* list_inser(struct db *pdb, int index, int num, int score)
{
struct db *p1 = NULL;
struct db *p2 = NULL;
struct db *p3 = NULL;
int count = 1;
p1 = pdb;
if ((NULL == pdb) && (0 != index))
{
printf("pdb is NULL, and index is not 0, it's %d\n", index);
return NULL;
}
if ((NULL == pdb) && (0 == index))
{
//空链表,然后要加入的是头节点
p2 = (struct db*) malloc(LEN);
if (NULL == p2)
{
printf("malloc error\n");
return NULL;
}
p2->num = num;
p2->score = score;
p2->next = NULL;
pdb = p2;
n += 1;
return pdb;
}
while ((NULL != p1) && (count != index))
{
p1 = p1->next;
count += 1;
}
p2 = (struct db*) malloc(LEN);
if (NULL == p2)
{
printf("malloc error\n");
return NULL;
}
p2->num = num;
p2->score = score;
p3 = p1->next;
p1->next = p2;
p2->next = p3;
n += 1;
return pdb;
}
struct db* list_remove(struct db *pdb, int index)
{
struct db *p1 = NULL;
struct db *p2 = NULL;
struct db *p3 = NULL;
int count = 1;
if (NULL == pdb)
{
printf("pdb is NULL\n");
return NULL;
}
p1 = pdb;
//一开始没有考虑要删头节点的情况,这个要单独考虑的,否则会core
if(1 == index)
{
pdb = pdb->next;
free(p1);
p1 = NULL;
return pdb;
}
while((NULL != p1) && (count != index))
{
p2 = p1; //保存当前节点,如果下一个节点就是的话,这个会用上
p1 = p1->next;
count+=1;
}
p2->next = p1->next;
free(p1);
p1 = NULL;
n-=1;
return pdb;
}
struct db* list_convert(struct db* pdb)
{
struct db* p1;
struct db* p2; //临时存储
struct db* p3; //最后输出的列表
p1 = pdb; //存储的初始的列表
//除head外的第一个节点的next要变成NULL
p3 = NULL;
while(NULL != p1)
{
p2 = p1->next;
p1->next = p3;
p3 = p1; //存储中间节点的
p1 = p2;
}
return p3;
}
//按照score排序
struct db* list_sort(struct db* pdb)
{
struct db* first; //有序链表的头指针
struct db* tail; //有序链表的尾指针
struct db* min; //最小值的节点
struct db* pre_min;//保存当前最小值节点的前驱节点,保存这个是为了后面重新调整链表用的
struct db* p;
if(NULL == pdb) return NULL;
while(NULL != pdb)
{
for(p = head,min=head;p->next!=NULL;p=p->next) //为什么是p->next != NULL不是p!=NULL,后来想了下确实不需要p!=NULL,因为一开始head已经判断过,后面next也是个节点
{
if(min->score > p->score)
{
//将值小的点放入新的链表
if(NULL == first)
{
first = p;
tail = NULL;
}
else
{
}
}
}
}
}
//写链表这类程序,关键是理解:head存储的是第一个节点的地址,
//head->next存储的是第二个节点的地址;任意一个节点p的地址,只能通过它前一个节点的next来求得
int main()
{
struct db *head = NULL;
int index = 0;
int insertnum = 0;
int inserscore = 0;
freopen("input.txt", "r", stdin);
//链表的创建
head = list_create();
int num = 20;
//链表查找
list_search(head, num);
//链表删除
/*1、 head就是第1个节点,head->next就是第2个节点;
2、删除后head指向第2个节点,就是让head=head->next。
---->[1]---->[2]---->[3]...---->[n]---->[NULL](原链表)
head 1->next 2->next 3->next n->next
---->[1]---->[3]...---->[n]---->[NULL](删除后链表)
head 1->next 3->next n->next*/
//scanf("%d", &index);
//head = list_remove(head, index);
list_print(head);
//链表反序
//原来的head头要跑到最后,原来的p1->next = p2变成p2->next=p1
//反序还是不理解,要背诵
head = list_convert(head);
//链表输出
list_print(head);
//链表增加
//指定节点插入
scanf("%d %d %d", &index, &insertnum, &inserscore);
head = list_inser(head, index, insertnum, inserscore);
//链表排序
head = list_sort(head);
return 0;
}