数据结构 C 代码 2.2: 单链表

单链表的创建, 添加, 插入, 删除.

1. 代码

先上代码, 再讲废话.

#include <stdio.h>
#include <malloc.h>

/**
 * Linked list of characters. The key is data.
 */
typedef struct LinkNode{
	char data;
	struct LinkNode *next;
} LNode, *LinkList, *NodePtr;

/**
 * Initialize the list with a header.
 * @return The pointer to the header.
 */
LinkList initLinkList(){
	NodePtr tempHeader = (NodePtr)malloc(sizeof(LNode));
	tempHeader->data = '\0';
	tempHeader->next = NULL;
	return tempHeader;
}// Of initLinkList

/**
 * Print the list.
 * @param paraHeader The header of the list.
 */
void printList(NodePtr paraHeader){
	NodePtr p = paraHeader->next;
	while (p != NULL) {
		printf("%c", p->data);
		p = p->next;
	}// Of while
	printf("\r\n");
}// Of printList

/**
 * Print the list with memeory information.
 * @param paraHeader The header of the list.
 */
void printListMemory(NodePtr paraHeader){
	NodePtr p = paraHeader;
	while (p != NULL) {
	    printf("At address %ld, data = %c, next = %ld \r\n", p, p->data, p->next);
		p = p->next;
	}// Of while
	printf("\r\n");
}// Of printListMemory


/**
 * Add an element to the tail.
 * @param paraHeader The header of the list.
 * @param paraChar The given char.
 */
void appendElement(NodePtr paraHeader, char paraChar){
	NodePtr p, q;

	// Step 1. Construct a new node.
	q = (NodePtr)malloc(sizeof(LNode));
	q->data = paraChar;
	q->next = NULL;

	// Step 2. Search to the tail.
	p = paraHeader;
	while (p->next != NULL) {
		p = p->next;
	}// Of while

	// Step 3. Now add/link.
	p->next = q;
}// Of appendElement

/**
 * Insert an element to the given position.
 * @param paraHeader The header of the list.
 * @param paraChar The given char.
 * @param paraPosition The given position.
 */
void insertElement(NodePtr paraHeader, char paraChar, int paraPosition){
	NodePtr p, q;

	// Step 1. Search to the position.
	p = paraHeader;
	for (int i = 0; i < paraPosition; i ++) {
		p = p->next;
		if (p == NULL) {
			printf("The position %d is beyond the scope of the list.", paraPosition);
			return;
		}// Of if
	} // Of for i

	// Step 2. Construct a new node.
	q = (NodePtr)malloc(sizeof(LNode));
	q->data = paraChar;

	// Step 3. Now link.
	printf("linking\r\n");
	q->next = p->next;
	p->next = q;
}// Of insertElement

/**
 * Delete an element from the list.
 * @param paraHeader The header of the list.
 * @param paraChar The given char.
 */
void deleteElement(NodePtr paraHeader, char paraChar){
	NodePtr p, q;
	p = paraHeader;
	while ((p->next != NULL) && (p->next->data != paraChar)){
		p = p->next;
	}// Of while

	if (p->next == NULL) {
		printf("Cannot delete %c\r\n", paraChar);
		return;
	}// Of if

	q = p->next;
	p->next = p->next->next;
	free(q);
}// Of deleteElement

/**
 * Unit test.
 */
void appendInsertDeleteTest(){
	// Step 1. Initialize an empty list.
	LinkList tempList = initLinkList();
	printList(tempList);

	// Step 2. Add some characters.
	appendElement(tempList, 'H');
	appendElement(tempList, 'e');
	appendElement(tempList, 'l');
	appendElement(tempList, 'l');
	appendElement(tempList, 'o');
	appendElement(tempList, '!');
	printf("After appendElement");
	printList(tempList);
	printListMemory(tempList);

	// Step 3. Delete some characters (the first occurrence).
	deleteElement(tempList, 'e');
	deleteElement(tempList, 'a');
	deleteElement(tempList, 'o');
	printf("After deleteElement");
	printList(tempList);
	printListMemory(tempList);

	// Step 4. Insert to a given position.
	insertElement(tempList, 'o', 1);
	printf("After insertElement");
	printList(tempList);
	printListMemory(tempList);
}// Of appendInsertDeleteTest

/**
 * Address test: beyond the book.
 */
void basicAddressTest(){
	LNode tempNode1, tempNode2;

	tempNode1.data = 4;
	tempNode1.next = NULL;

	tempNode2.data = 6;
	tempNode2.next = NULL;

	printf("The first node: %d, %d, %d\r\n",
		&tempNode1, &tempNode1.data, &tempNode1.next);
	printf("The second node: %d, %d, %d\r\n",
		&tempNode2, &tempNode2.data, &tempNode2.next);

	tempNode1.next = &tempNode2;
}// Of basicAddressTest

/**
 * The entrance.
 */
int main(){
	appendInsertDeleteTest();
}// Of main

2. 运行结果

Hello!
Cannot delete a
Hll!
linking
Holl!
Press any key to continue

3. 代码说明

  1. 只需要定义一个节点类型, 空间只受内存堆空间的限制.
  2. 抓住了头节点, 就抓住了整个世界.
  3. 可以根据循环语句, 分析时间复杂度.
  4. 这里必须用图示来分析 append, insert, delete 操作.
  5. basicAddressTest 用于观察地址分配. 多写几个这样的函数, 就更理解操作系统的机制.

3. 作业

  1. 抄代码.
  2. 进行 insertElement 等函数进一步的测试.
  3. 挑本贴 bug 并留言.
  4. 写 CSDN 博客. 必须有图示, 可以用工具画, 或者手绘拍照.

附 1: 2021 代码

何雪晴同学的代码, 但使用 CodeBlocks 进行了格式调整.

#include <stdio.h>
#include <stdlib.h>

typedef struct LNode
{
    ElemType data;
    struct LNode *next;
} LNode,*LinkList; //单链表的储存结构

int main()
{
    CJYNode*p;
    LinkList L=NULL;
    int length,i,j,k,m,n;
    i=9;
    j=5;
    k=2;
    n=10;
    L= CreateList1();
    L = CreateList2();
    length=ListLength(L);
    printf("单链表长度为;%d\n",length);

    p=GetList(L,k);
    printf("位置查找第%d个位置的元素是;%d\n",k,p->data);

    m=LocateElem(L,j);
    printf("数值查找为%d的元素的位置是%d\n",j,m);

    ListInsert(L,i,j);
    ListDelete(L,i);
}

Status InitList(LinkList &L)
{
    L=new LNode;
    L->next=NULL;
    return OK;
} //单链表的初始化

Status GetElem(LinkList L,int i,ElemType &e)
{
    p=L->next;
    j=1;
    while(p&&j<i)
    {
        p=p->next;
        ++j;
    }
    if(!p||j>i)
        return ERROR;
    e=p->data;
    return OK;
} //单链表的取值

LNOde *LocateElem(LinkList L,ElemType e)
{
    p=L->next;
    while(p&&p->data!=e)
    {
        p=p->next;
    }
    return p;
} //单链表的按值查找

Status ListInsert(LinkList &L,int i,ElemType e)
{
    p=L;
    j=0;
    while(p&&(j,i-1))
    {
        p=p->next;
        ++j;
    }
    if(!p||j>i-1)
        return ERROR;
    a=new LNOde;
    s->data=e;
    s->next=p->next;
    p->next=s;
    return OK;
} //单链表的插入
Status ListDelete(LinkList &L,int i)
{
    p=L;
    j=0;
    while((p->next)&&(j<i-1))
    {
        p=p->next;
        ++j;
    }
    if(!(p->next)||(j>i-1))
        return ERROR;
               q=p->next;
    p->next=q->next;
    delete q;
    return OK;
}//单链表的删除

void CreateList_H(LinkList &L,int n)
{
    L=new LNode;
    L->next=NULL;
    for(i=0; i<n; ++i)
    {
        p=new LNode;
        cin>>p->data;
        p->next=L->next;
        L->next=p;
    }
}//前插法创建单链表

欢迎留言!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值