C中的typedef
C中的typedef关键字作用是为一种数据类型定义一个新名字,这样做的目的有两个,一是给变量定义一个易记且意义明确的新名字,如:
typedef unsigned char BYTE;
把unsigned char类型自命名为BYTE。
另一个目的是简化一些比较复杂的类型声明,比如struct结构类型:
typedef struct student
{
int age;
int class;
}stu;
stu stu_1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候
struct student stu_1; //以上等价于这种定义,C中规定声明struct对象时需要加struct关键字
使用typedef定义结构体指针
如下定义:
typedef struct TreeNode {
int Element;
struct TreeNode* LeftChild;
struct TreeNode* RightChild;
} Node,*PtrToTreeNode;
等价于:
给结构体 TreeNode 起一个别名为 Node;
给结构体指针 TreeNode* 起一个别名为 PtrToTreeNode; 即PtrToTreeNode实际上是一个指针!
单链表基本操作
链表是一种线性存储数据的结构(线性结构是一种数据的逻辑结构,其他还有树结构、图结构和集合结构)。链表的存储内容在逻辑上连续,但物理上不一定连续。单向链表的组成包括:
- 表头(head):只有指针域,没有数据域;
- 结点(node):数据域+指针域;
- 表尾:只有数据域,没有指针域(指针为NULL);
单链表结点(node)的定义:
struct node{
int num;
struct node* Pnext;
}
C语言中链表的实现主要依靠结构体和指针。
实现单链表的 创建、打印、计算长度、删除指定结点、头尾插入、链表递增排序、逆序、清空链表等操作:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//定义单链表结点结构
typedef struct Node{
int data;
struct Node* next;
}node;
//创建带表头单向链表,表尾插入
node* createList(const int length){
node *head,*helper;
helper = head = (node *)malloc(sizeof(node));
for(int i=0;i<length;i++){
helper = helper->next = (node *)malloc(sizeof(node));
helper->data = i;
}
helper->next = NULL;
return head;
}
//打印链表
void printList(const node* list1){
const node* p=NULL;
p = list1->next; //有表头链表指向表头后的结点
while(p){
printf("%d\n",p->data);
p = p->next;
}
}
// 求链表长度
int length_list(const node* list1){
int n=0;
if(list1->next==NULL){
return n;
}
while(list1->next!=NULL){
n+=1;
list1=list1->next;
}
return n;
}
//删除数据域值为key的结点
node* delete_key(node* list1, int key){
if(list1->next==NULL){
return list1; //如果为空直接返回
}
node* p, *del;
for(p=list1;p->next!=NULL&&p->next->data!=key;p=p->next);
if(p->next==NULL){
return list1; //如果到最后一个结点还没有匹配到key,返回list1
}
del = p->next;
p->next=p->next->next;
free(del);
del = NULL;
return list1;
}
//在头结点或尾结点插入数据key
node* insert_list(node* list1, int key, int head_or_end){
node* insert_key = (node*)malloc(sizeof(node));
insert_key->data = key;
if(head_or_end){
insert_key->next = list1->next;
list1->next = insert_key;
return list1;
}
else{
node* p = list1;
for(p = list1; p->next!=NULL;p=p->next);
p->next = insert_key;
insert_key->next = NULL;
return list1;
}
}
//单链表排序(表头到表尾增大)
node* sort_list(node* list1){
int length = length_list(list1);
if(length==0){ //长度为0表示空链表,返回
return list1;
}
for(int i=1;i<length;i++){
node* p = list1->next;
for(int j=0;j<length-i;j++){
if(p->data>p->next->data){
p->data+=p->next->data;
p->next->data = p->data - p->next->data;
p->data = p->data - p->next->data;
}
p=p->next;
}
}
return list1;
}
//单链表逆序
node* reverse_list(node* list1){
if(list1==NULL||list1->next==NULL){
return list1;
}
node *p1, *p2, *p3;
node *head = (node*)malloc(sizeof(node));
p1 = list1;
p2 = p1->next;
while(p2!=NULL){
p3 = p2->next;
p2->next = p1;
p1 = p2;
p2 = p3;
}
list1->next->next=NULL;
head->next = p1;
list1 = head;
return list1;
}
//清空单链表
void delete_all(node* list1){
node* p1=NULL,*p2 = NULL;
p1 = list1->next;
while(p1->next!=NULL){
p2 = p1->next;
free(p1);
p1 = p2;
}
free(p2);
list1->next=NULL;
}
void main()
{
node* List1 =createList(5); //创建链表
printList(List1); //打印链表
printf("%d\n",length_list(List1)); //链表长度
List1 = delete_key(List1,3); //删除链表结点
List1 = insert_list(List1,66,1); //头结点插入数据
List1 = insert_list(List1,77,0); //尾结点插入数据
List1 = sort_list(List1); //链表递增排序
printList(List1);
List1 = reverse_list(List1); //链表逆序
printList(List1);
delete_all(List1); //清空销毁链表
printf("%d\n",length_list(List1));
return;
}
补充两个操作: 头插法和查找中间结点:
// 表头插入
node* create_list_headIN(const int length){
node* head = (node*)malloc(sizeof(node));
node* p;
for(int i=0;i<length;i++){
p = (node*)malloc(sizeof(node));
p->data = i;
p->next = head->next;
head->next = p;
}
head ;
return head;
}
//查找链表中间结点
node* middle_node(node* list1){
node *p1,*p2;
p1 = p2 = list1;
while(p2 && p2->next){
p1 = p1->next;
p2 = p2->next->next;
}
printf("\n%d\n",p1->data);
return p1;
}