单链表创建

单链表的创建与操作

链表作为基本的数据结构,学习好链表的创建与操作是数据结构入门的基础。
(小白make for myself)

单链表的创建

typedef struct Node {
    int data;
    struct Node* next;
}Node;//结构体创建,也可以使用*Node取址
Node* initList() {
    Node* L = (Node*)malloc(sizeof(Node));//动态分配存储单元
    L -> data = 0;
    L -> next = NULL;
    return L;
}

单链表的插入

单链表的头插法

所谓头插法就是在链表头节点和第一个元素之间进行插入数据元素

void headInsert(Node* L, int data)
{
    Node* node = (Node*)malloc(sizeof(Node));
    node -> data = data;
    node -> next = L->next;
    L -> next = node;
    L -> data ++;//头节点的数据域存放链表元素个数
}

单链表的尾插法

所谓尾插法就是在链表的尾部进行插入结点

void tailInsert(Node* L, int data) 
{
    Node* node = L;//复制头节点
    for(int i = 0; i < L -> data; i++) {
        node = node->next;
    }//遍历到原链表最后节点处
    Node* n = (Node*)malloc(sizeof(Node));//创建新的结点动态分配存储空间
    n -> data = data;
    n -> next = NULL;//尾结点为空
    node -> next = n;//使原链表尾结点指针指向新定义的结点
    L -> data ++;//头节点存放数据+1
}

遍历单链表的结点

通过调用子函数来实现链表的遍历以及打印到显示屏幕上

void printList(Node* L) 
{
    Node* node = L -> next;//创建新节点为原链表第一个结点(除头节点)
    while(node)//当node不为NULL时,为空时为尾结点跳出
    {
        printf("node = %d\n", node -> data);
        node = node -> next;//指向下一个结点
    }
}

链表的冒泡排序(改进)

Node* maopao(Node* head)//改进型冒泡排序 
{
	Node *p,*q;
	int num=0,j=0;
	q=head;
	//获取链表的长度 
	while(q!=NULL){
		q=q->next;
		num++;
	}
	//冒泡排序的基本思路 
	for(int i=0;i<num-1;i++)
		{
			p=q=head; 
			j=num-i-1; //减少每一趟循环中两两比较的次数 
			while(p->next!=NULL&&j!=0)
			{
				j--;
				if(p->data>p->next->data)
				{
					//节点的交换 
					if(p==head) head=p->next;
					else q->next=p->next;
					q->next=p->next;
					q=q->next;
					p->next=q->next;
					q->next=p;
					//执行完上面的过程后,为了能够让p顺利地执行移动到交换后的下一位 . 
					p=q; 
				}
				q=p; //为了能让q保持在p的前面 
				p=p->next; //p指针后移,即p变成了在q的前面 
				SortDir++;//记录比较次数
			}
		}
	return head;
}

综合实现

#include 
#include 

int SortDir = 0;//用作改进冒泡排序计数
int SortDir2 = 0;//记录普通排序方法 
typedef struct Node 
{
    int data;
    struct Node* next;
}Node;

Node* initList() {
    Node* L = (Node*)malloc(sizeof(Node));
    L -> data = 0;
    L -> next = NULL;
    return L;
}

void headInsert(Node* L, int data) {
    Node* node = (Node*)malloc(sizeof(Node));
    node -> data = data;
    node -> next = L->next;
    L -> next = node;
    L -> data ++;
}

void tailInsert(Node* L, int data) {
    Node* node = L;
    for(int i = 0; i < L -> data; i++) {
        node = node->next;
    }
    Node* n = (Node*)malloc(sizeof(Node));
    n -> data = data;
    n -> next = NULL;
    node -> next = n;
    L -> data ++;
}

void printList(Node* L) {
    Node* node = L -> next;
    while(node){
        printf("node = %d\n", node -> data);
        node = node -> next;
    }
}

Node* maopao(Node* head)//改进型冒泡排序 
{
    Node *p,*q;
    int num=0,j=0;
    q=head;
    //获取链表的长度 
    while(q!=NULL){
        q=q->next;
        num++;
    }
    //冒泡排序的基本思路 
    for(int i=0;i<num-1;i++)
        {
            p=q=head; 
            j=num-i-1; //减少每一趟循环中两两比较的次数 
            while(p->next!=NULL&&j!=0){
                j--;
                if(p->data>p->next->data){
                    //节点的交换 
                    if(p==head) head=p->next;
                    else q->next=p->next;
                    q->next=p->next;
                    q=q->next;
                    p->next=q->next;
                    q->next=p;
                    //执行完上面的过程后,为了能够让p顺利地执行移动到交换后的下一位 . 
                    p=q; 
                }
                q=p; //为了能让q保持在p的前面 
                p=p->next; //p指针后移,即p变成了在q的前面 
                SortDir++;
            }
        }
    return head;
}

Node* maopao1(Node* head){
    Node *p,*q;
    int num=0,j=0;
    q=head;
    //获取链表的长度 
    while(q!=NULL){
        q=q->next;
        num++;
    }
    //冒泡排序的基本思路 
    for(int i=0;i<num-1;i++)
        {
            p=q=head; 
            while(p->next!=NULL){
                if(p->data>p->next->data){
                    //节点的交换 
                    if(p==head) head=p->next;
                    else q->next=p->next;
                    q->next=p->next;
                    q=q->next;
                    p->next=q->next;
                    q->next=p;
                    //执行完上面的过程后,为了能够让p顺利地执行移动到交换后的下一位 . 
                    p=q; 
                }
                q=p; //为了能让q保持在p的前面 
                p=p->next; //p指针后移,即p变成了在q的前面 
                SortDir2++;//非改进型冒泡排序比较次数
            }
        }
    return head;
}

int main()
{

    int elems[30];
    int n,Dir;
    Node* L = initList();
    Node* L1 = initList();
    printf("please enter your num of line(max ==30) \n");
    scanf("%d", &n);//用户输入数字数量
    Dir = n;//只是为了提示还能输入多少个字符
    for (int i = 0; i < n;i++)//用户输入int类型的循环 
    {
        printf("pleast enter your numbers one(remain%d) \n",Dir);
        scanf("%d", &elems[i]);//用户输入数据,便于储存
        tailInsert(L, elems[i]);
        tailInsert(L1,elems[i]); 
        Dir--;
    }
    printf("original num:\n");
    printList(L);
    maopao (L);
    printf("the after nums (正序):\n");
    printList(L);
    printf("The Sort nums(改进正序次数):%d\n",SortDir);
    maopao1 (L1);
    printf("the after nums (正序):\n");
    printList(L1);
    printf("The Sort nums(普通排序正序次数):%d\n",SortDir2);
    SortDir = 0;
    system("pause");
    return 0;
}

运行结果

正序输入结果
单链表创建_第1张图片
逆序输入结果
单链表创建_第2张图片

乱序输入结果
单链表创建_第3张图片
输入、输出结果:在以上三种顺序输入数据时我们可以看到,两种冒泡排序方法都可以正确地进行排序,并输出排序结果和排序次数供我们直观地查看区别。

你可能感兴趣的:(链表,数据结构,算法)