赞
踩
struct 结构体类型名 结构体变量列表;
结构体四种写法
1. struct stu{
......};//保留结构体类型名
2. struct {
.....}stu[10];//省略结构体类型名
3. typedef struct stu{
.......}STU;
stu s[10];
STU s[10];//即使重命名后也可以用原来的名字定义
4. typedef struct {
.......}STU;
STU s[10];
结构体变量名 . 成员名
(*结构体指针变量名). 成员名 (点的运算优先级高于星号)
结构体指针变量名 -> 成员名
struct stu_node{
char num[10];
char name[10];
int c;//以上为数据域
struct stu_node *next;//指向下一个结点的指针(指针域)
};
struct stu_node *head, *newN, *tail;
*head 为头指针指向链表的第一个结点
*newN用来指向新建结点,他既可以操作数据域也可以操作指针域
*tail用来指向链表的尾结点
结点 = 数据域 + 指针域
1.单链表的储存结构
typedef int ElemType;
typedef struct Node{
ElemType data;
struct Node *next;
}Node, *Linklist;//*Linklist为结构体指针类型
此处*Linklist
与Node*
等价,通常使用定义LinkList L
,L为单链表的头指针,使用Node* p
来定义指向单项链表结点的指针
2.初始化单链表
InitList(Linklist *L)//InitList(Node* *L)
{
*L = (Linklist)malloc(sizeof(Node));
(*L) -> next = NULL;//建立空的单链表L
}
L
(形参)是指单链表头节点的指针,用于接收待初始化单链表的头指针变量的地址,故调用该函数时实参前要加&
*L
相当于主程序中带初始化单链表的头指针变量
3.建立链表
(1)头插法建表
void CreateFromHead(LinkList L) { //L是带头节点的空链表头指针 Node *s; char c; while(1) { //如果输入$则表示停止新建下一个结点,建表结束 scanf("%c", &c); if(strcmp(c, "$") == 0) break; s = (Node*)malloc(sizeof(Node)); s->data = c; //头插法: s->next = L->next; L->next = s; } }
(2)尾插法建表
void CreateFromTail(LinkList L) { Node *r, *s; char c; r = L;//建表前L是空表,仅有头结点,表头即是表尾 while(1) { //如果输入$则表示停止新建下一个结点,建表结束 scanf("%c", &c); if(strcmp(c, "$") == 0) { //建表结束时将尾结点next指针链域置空 r->next = NULL; break; } s = (Node*)malloc(sizeof(Node)); s->data = c; //尾插法: r->next = s; r = s;//记得移动尾指针 }
(3)按位查找
Node* Locate(LinkList L, int i)
{
//查找第i个结点,i的合法范围1≤i≤n
int cnt;
Node *p;
if(i <= 0 || i > n) return NULL;
p = L;
for(cnt = 0;(p->next != NULL)&&(cnt < i);cnt++)
p = p->next;
return p;
}
算法时间复杂度
O
(
n
)
O(n)
O(n)
(4)按值查找
Node* GetData(LinkList L, ElemType key)
{
Node *p;
p = L->next;//从第一个结点开始查找
while(p != NULL)
{
if(p->data == key) break;
p = p->next;
}
return p;
}
算法时间复杂度
O
(
n
)
O(n)
O(n)
(5)求链表长度
int ListLength(LinkList L)
{
int cnt;
Node *p;
p = L->next;
while(p != NULL)
{
p = p->next;
cnt++;
}
return cnt;
}
(6)单链表插入操作
void InsList(LinkList L, int i, ElemType e)
{
int cnt;
Node *pre, *s;
if(i <= 0) return;
pre = L;
for(cnt = 0;pre->NULL;
1.开辟一个新结点
newN = (struct_node *)malloc(sizeof(struct_node));
strcpy(newN -> num, num);
newN -> score = score;//先用newN指针指向变量给数据域中的变量赋值
newN -> next = NULL;
//再用newN指针操作指针域的next指针,由于现在只有一个结点所以定义三个指针都指向他,由于tail指针也指向它所以把next指针置为空
2.将新结点连接到表位
(1)对于空表即新结点是链表的第一个结点
head = newN;
将头指针指向新结点
(2)对于非空表,将新结点链接到尾结点之后
tail->next = newN;
让尾指针找到并指向next后让next指向新结点
(3)将链表尾指针指向新结点
tail->newN;
3.一个标准范例
#include<stdio.h> #include<stdlib.h> #include<string.h> struct stu_node{ char num[10]; int score; struct stu_node *next; }; struct stu_node *stu_create() { struct stu_node *head, *newN, *tail; char num[10]; int score; //创建第一个结点并输入数据 scanf("%s%d", num, &score); newN = (struct_node *)malloc(sizeof(struct_node)); strcpy(newN -> num, num); newN -> score = score; newN -> next = NULL; head = newN; tail = newN; //继续创建后续结点 while(1){ scanf("%s", num); if(strcmp(num, "0") == 0) break; else { scanf("%d", &score); newN = (struct_node *)malloc(sizeof(struct_node)); newN -> score = score; newN -> next = NULL;//新结点使next指针暂时置空 tail -> next = newN;//前一个结点的尾指针使next指针指向新结点 tail = newN;//尾指针指向新结点 } } return head; }
PS:此处新建结点最常见的错误就是写成指针++,但是请注意结点在内存中所占的储存空间并不一定连续,所以不能用这种方式来移动指针
1.输出
void stu_print(struct stu_node *head)
{
struct stu_node *p = head;
if(p == NULL)//这就是为啥尾结点的next指针置空的原因
{
printf("学生信息为空!");
return;
}
printf("学号\t分数\n");
while( p != NULL)
{
printf("%s%d", p -> num, p -> score);
p = p -> next;//p指向下一个结点
}
}
2.修改
void stu_modify(struct stu_node *head) { char num[10]; struct stu_node *p = head; if(head == NULL) { printf("学生信息为空!"); return; } printf("请输入要修改学生的学号:"); scanf("%s", num); while(strcmp(p -> num, num) != 0 && p != NULL) p = p -> next; if(p != NULL) { printf("请输入要修改学生的分数:"); scanf("%d", &p -> score); } else printf("未找到该学号学生!"); }
3.删除
struct_node *stu_delete(struct stu_node *head) { char num[15]; struct stu_node *p = head, *q; if(p == NULL) { printf("学生信息为空!"); return; } printf("请输入要删除学生的学号:"); scanf("%s", num); while(strcmp(p -> num, num) != 0 && p != NULL) { q = p; p = p -> next; } if(p != NULL) { if(p == head) head = p -> next;//头指针指向待删结点的下一个结点 else q -> next = p -> next;//前一个指针结点指向待删结点的下一个结点 free(p);//释放待删除结点所占内存空间 } else printf("未找到该学号的学生"); return head; }
编写教职工系统
编写程序,在主函数中调用create函数创建链表,调用findmax函数找到年龄最大的职工,del函数删除一个职工(要删除的职工编号在主函数中输入,并存放在number字符数组中)。
员工结构体的定义如下:
typedef struct wrk_node
{
char num[15];
int age;
struct wrk_node * next;
}WORKER;
//建立链表函数,返回头指针,当职工号为0时结束输入
WORKER * create( )
{
}
//查找年龄最大的职工,并返回指针
WORKER * findmax(WORKER *head)
{
}
//删除职工,number中为删除的职工号,返回头指针
WORKER * del( WORKER *head ,char number[ ])
{
}
程序如下:
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct wrk_node { char num[15]; int age; struct wrk_node *next; }WORKER; WORKER * create(); WORKER * findmax(WORKER *head); WORKER * del( WORKER *head ,char number[ ]); void print(WORKER *head); int main() { WORKER *head = NULL, *max; printf("----------------------------------------------\n"); printf("Welcome To The Administration Of The Staffs!\n"); printf("1.New\n"); printf("2.Age Findmax\n"); printf("3.Del\n"); printf("4.Print\n"); printf("----------------------------------------------\n"); int choice; while(1) { printf("Please choose a number(1-4)\n"); scanf("%d", &choice); switch(choice) { case 1:head = create();break; case 2:max = findmax(head); printf("年龄最大的职工的工号为%s\n", max -> num); printf("其年龄是%d岁\n", max -> age); break; case 3:char number[15]; printf("请输入要删除职工的工号:"); scanf("%s", number); head = del(head, number);break; case 4:print(head);break; default:exit(0); } } return 0; } //建立链表函数,返回头指针,当职工号为0时结束输入 WORKER *create() { WORKER *head, *newN, *tail; char num[15]; newN = (WORKER*)malloc(sizeof(WORKER)); printf("请输入职工的工号和年龄:"); scanf("%s%d", newN -> num, &newN -> age); newN -> next = NULL; head = newN; tail = newN; while(1) { printf("请输入职工的工号和年龄:"); scanf("%s", num); if(strcmp(num, "0") == 0) break; else{ newN = (WORKER*)malloc(sizeof(WORKER)); strcpy(newN -> num, num); scanf("%d", &newN -> age); newN -> next = NULL; tail -> next = newN; tail = newN; } } return head; } //查找年龄最大的职工,并返回指针 WORKER * findmax(WORKER *head) { WORKER *p = head, *max = head; while(p != NULL) { if(p -> age > max -> age) max = p; p = p -> next; } return max; } //删除职工,number中为删除的职工号,返回头指针 WORKER *del(WORKER *head, char number[ ]) { WORKER *p = head, *q; while((strcmp(p -> num, number) != 0) && (p != NULL)) { q = p; p = p -> next; } if(p != NULL) { if(p == head) head = p -> next; else q -> next = p -> next; free(p); } return head; } //输出 void print(WORKER *head) { WORKER *p = head; printf("工号\t年龄\n"); while(p != NULL) { printf("%s\t%d\n", p -> num, p ->age); p = p -> next; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。